Commit 31aded61d8c05fc76162e2719f42fd824b641981
1 parent
6aa235e4
feat(pms): add project and knowledge management
Showing
320 changed files
with
31954 additions
and
1 deletions
Too many changes.
To preserve performance only 100 of 320 files are displayed.
pom.xml
| @@ -28,7 +28,8 @@ | @@ -28,7 +28,8 @@ | ||
| 28 | <!-- <module>yudao-module-wms</module>--> | 28 | <!-- <module>yudao-module-wms</module>--> |
| 29 | <!-- <module>yudao-module-hrm</module>--> | 29 | <!-- <module>yudao-module-hrm</module>--> |
| 30 | <!-- <module>yudao-module-fms</module>--> | 30 | <!-- <module>yudao-module-fms</module>--> |
| 31 | - <!-- <module>yudao-module-im</module>--> | 31 | + <module>yudao-module-pms</module> |
| 32 | +<!-- <module>yudao-module-im</module>--> | ||
| 32 | <!-- 请参考 https://doc.iocoder.cn/ai/build/ 文档,完成 AI 模块的启动!!! --> | 33 | <!-- 请参考 https://doc.iocoder.cn/ai/build/ 文档,完成 AI 模块的启动!!! --> |
| 33 | <!-- <module>yudao-module-ai</module>--> | 34 | <!-- <module>yudao-module-ai</module>--> |
| 34 | </modules> | 35 | </modules> |
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/StringListConvert.java
| 1 | package cn.iocoder.yudao.framework.excel.core.convert; | 1 | package cn.iocoder.yudao.framework.excel.core.convert; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | import cn.idev.excel.converters.Converter; | 5 | import cn.idev.excel.converters.Converter; |
| 5 | import cn.idev.excel.metadata.GlobalConfiguration; | 6 | import cn.idev.excel.metadata.GlobalConfiguration; |
| 7 | +import cn.idev.excel.metadata.data.ReadCellData; | ||
| 6 | import cn.idev.excel.metadata.data.WriteCellData; | 8 | import cn.idev.excel.metadata.data.WriteCellData; |
| 7 | import cn.idev.excel.metadata.property.ExcelContentProperty; | 9 | import cn.idev.excel.metadata.property.ExcelContentProperty; |
| 8 | 10 | ||
| 11 | +import java.util.Collections; | ||
| 9 | import java.util.List; | 12 | import java.util.List; |
| 10 | 13 | ||
| 11 | /** | 14 | /** |
| @@ -15,6 +18,25 @@ import java.util.List; | @@ -15,6 +18,25 @@ import java.util.List; | ||
| 15 | */ | 18 | */ |
| 16 | public class StringListConvert implements Converter<List<String>> { | 19 | public class StringListConvert implements Converter<List<String>> { |
| 17 | 20 | ||
| 21 | + /** | ||
| 22 | + * 将 Excel 单元格中的分隔字符串解析为字符串列表。 | ||
| 23 | + * | ||
| 24 | + * @param value Excel 单元格数据 | ||
| 25 | + * @param contentProperty Excel 字段属性 | ||
| 26 | + * @param globalConfiguration Excel 全局配置 | ||
| 27 | + * @return 字符串列表 | ||
| 28 | + */ | ||
| 29 | + @Override | ||
| 30 | + public List<String> convertToJavaData(ReadCellData<?> value, ExcelContentProperty contentProperty, | ||
| 31 | + GlobalConfiguration globalConfiguration) { | ||
| 32 | + String text = value == null ? null : value.getStringValue(); | ||
| 33 | + if (StrUtil.isBlank(text)) { | ||
| 34 | + return Collections.emptyList(); | ||
| 35 | + } | ||
| 36 | + // 兼容导入模板常用的英文逗号、中文逗号、顿号,以及导出时使用的斜杠。 | ||
| 37 | + return StrUtil.splitTrim(text.replace(',', ',').replace('、', ',').replace('/', ','), ','); | ||
| 38 | + } | ||
| 39 | + | ||
| 18 | @Override | 40 | @Override |
| 19 | public WriteCellData<String> convertToExcelData(List<String> value, | 41 | public WriteCellData<String> convertToExcelData(List<String> value, |
| 20 | ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { | 42 | ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java
| @@ -50,6 +50,10 @@ public class BannerApplicationRunner implements ApplicationRunner { | @@ -50,6 +50,10 @@ public class BannerApplicationRunner implements ApplicationRunner { | ||
| 50 | if (isNotPresent("cn.iocoder.yudao.module.wms.framework.web.config.WmsWebConfiguration")) { | 50 | if (isNotPresent("cn.iocoder.yudao.module.wms.framework.web.config.WmsWebConfiguration")) { |
| 51 | System.out.println("[WMS 仓库管理系统 yudao-module-wms - 已禁用][参考 https://doc.iocoder.cn/wms/build/ 开启]"); | 51 | System.out.println("[WMS 仓库管理系统 yudao-module-wms - 已禁用][参考 https://doc.iocoder.cn/wms/build/ 开启]"); |
| 52 | } | 52 | } |
| 53 | + // PMS 系统 | ||
| 54 | + if (isNotPresent("cn.iocoder.yudao.module.pms.framework.web.config.PmsWebConfiguration")) { | ||
| 55 | + System.out.println("[PMS 项目管理系统 yudao-module-pms - 已禁用][请在 yudao-server 中开启]"); | ||
| 56 | + } | ||
| 53 | // CRM 系统 | 57 | // CRM 系统 |
| 54 | if (isNotPresent("cn.iocoder.yudao.module.crm.framework.web.config.CrmWebConfiguration")) { | 58 | if (isNotPresent("cn.iocoder.yudao.module.crm.framework.web.config.CrmWebConfiguration")) { |
| 55 | System.out.println("[CRM 系统 yudao-module-crm - 已禁用][参考 https://doc.iocoder.cn/crm/build/ 开启]"); | 59 | System.out.println("[CRM 系统 yudao-module-crm - 已禁用][参考 https://doc.iocoder.cn/crm/build/ 开启]"); |
yudao-module-pms/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <parent> | ||
| 6 | + <groupId>cn.iocoder.boot</groupId> | ||
| 7 | + <artifactId>yudao</artifactId> | ||
| 8 | + <version>${revision}</version> | ||
| 9 | + </parent> | ||
| 10 | + <modelVersion>4.0.0</modelVersion> | ||
| 11 | + | ||
| 12 | + <artifactId>yudao-module-pms</artifactId> | ||
| 13 | + <packaging>jar</packaging> | ||
| 14 | + | ||
| 15 | + <name>${project.artifactId}</name> | ||
| 16 | + <description> | ||
| 17 | + pms 包下,项目管理(Project Management System) | ||
| 18 | + 例如说:项目、工作事项、迭代、看板、工时和知识库等等 | ||
| 19 | + </description> | ||
| 20 | + | ||
| 21 | + <dependencies> | ||
| 22 | + <dependency> | ||
| 23 | + <groupId>cn.iocoder.boot</groupId> | ||
| 24 | + <artifactId>yudao-module-system</artifactId> | ||
| 25 | + <version>${revision}</version> | ||
| 26 | + </dependency> | ||
| 27 | + <dependency> | ||
| 28 | + <groupId>cn.iocoder.boot</groupId> | ||
| 29 | + <artifactId>yudao-module-infra</artifactId> | ||
| 30 | + <version>${revision}</version> | ||
| 31 | + </dependency> | ||
| 32 | + | ||
| 33 | + <!-- Web 相关 --> | ||
| 34 | + <dependency> | ||
| 35 | + <groupId>cn.iocoder.boot</groupId> | ||
| 36 | + <artifactId>yudao-spring-boot-starter-web</artifactId> | ||
| 37 | + </dependency> | ||
| 38 | + <dependency> | ||
| 39 | + <groupId>cn.iocoder.boot</groupId> | ||
| 40 | + <artifactId>yudao-spring-boot-starter-security</artifactId> | ||
| 41 | + </dependency> | ||
| 42 | + | ||
| 43 | + <!-- DB 相关 --> | ||
| 44 | + <dependency> | ||
| 45 | + <groupId>cn.iocoder.boot</groupId> | ||
| 46 | + <artifactId>yudao-spring-boot-starter-mybatis</artifactId> | ||
| 47 | + </dependency> | ||
| 48 | + | ||
| 49 | + <!-- Job 定时任务相关 --> | ||
| 50 | + <dependency> | ||
| 51 | + <groupId>cn.iocoder.boot</groupId> | ||
| 52 | + <artifactId>yudao-spring-boot-starter-job</artifactId> | ||
| 53 | + </dependency> | ||
| 54 | + | ||
| 55 | + <!-- Test 测试相关 --> | ||
| 56 | + <dependency> | ||
| 57 | + <groupId>cn.iocoder.boot</groupId> | ||
| 58 | + <artifactId>yudao-spring-boot-starter-test</artifactId> | ||
| 59 | + <scope>test</scope> | ||
| 60 | + </dependency> | ||
| 61 | + </dependencies> | ||
| 62 | + | ||
| 63 | +</project> |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/PmsKnowledgeContentPermissionController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.permission.PmsKnowledgeContentPermissionRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.permission.PmsKnowledgeContentPermissionUpdateReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.content.PmsKnowledgeContentPermissionDO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.content.PmsKnowledgeContentPermissionMemberDO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeContentPermissionService; | ||
| 11 | +import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||
| 12 | +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||
| 13 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 14 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 15 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 16 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 17 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 18 | +import jakarta.annotation.Resource; | ||
| 19 | +import jakarta.validation.Valid; | ||
| 20 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 21 | +import org.springframework.validation.annotation.Validated; | ||
| 22 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 23 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 25 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 27 | +import org.springframework.web.bind.annotation.RestController; | ||
| 28 | + | ||
| 29 | +import java.util.List; | ||
| 30 | +import java.util.Map; | ||
| 31 | + | ||
| 32 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 33 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 34 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 35 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 36 | + | ||
| 37 | +@Tag(name = "管理后台 - PMS 知识内容协作权限") | ||
| 38 | +@RestController | ||
| 39 | +@RequestMapping("/pms/kb/content-permission") | ||
| 40 | +@Validated | ||
| 41 | +public class PmsKnowledgeContentPermissionController { | ||
| 42 | + | ||
| 43 | + @Resource | ||
| 44 | + private PmsKnowledgeContentPermissionService permissionService; | ||
| 45 | + | ||
| 46 | + @Resource | ||
| 47 | + private AdminUserApi adminUserApi; | ||
| 48 | + @Resource | ||
| 49 | + private DeptApi deptApi; | ||
| 50 | + | ||
| 51 | + @GetMapping("/get") | ||
| 52 | + @Operation(summary = "获得知识内容协作权限") | ||
| 53 | + @Parameter(name = "id", description = "协作权限编号", required = true, example = "1024") | ||
| 54 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 55 | + public CommonResult<PmsKnowledgeContentPermissionRespVO> getContentPermission(@RequestParam("id") Long id) { | ||
| 56 | + Long userId = getLoginUserId(); | ||
| 57 | + PmsKnowledgeContentPermissionDO permission = permissionService.getContentPermission(id, userId); | ||
| 58 | + List<PmsKnowledgeContentPermissionMemberDO> members = permissionService.getContentPermissionMemberList(id, userId); | ||
| 59 | + Integer currentUserLevel = permissionService.getCurrentUserContentPermissionLevel( | ||
| 60 | + id, permission.getLibraryId(), userId); | ||
| 61 | + return success(buildPermissionRespVO(permission, members, currentUserLevel)); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + @PutMapping("/update") | ||
| 65 | + @Operation(summary = "更新知识内容协作权限") | ||
| 66 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 67 | + public CommonResult<Boolean> updateContentPermission(@Valid @RequestBody PmsKnowledgeContentPermissionUpdateReqVO updateReqVO) { | ||
| 68 | + permissionService.updateContentPermission(updateReqVO, getLoginUserId()); | ||
| 69 | + return success(true); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + // ==================== 拼接 VO ==================== | ||
| 73 | + | ||
| 74 | + private PmsKnowledgeContentPermissionRespVO buildPermissionRespVO(PmsKnowledgeContentPermissionDO permission, | ||
| 75 | + List<PmsKnowledgeContentPermissionMemberDO> members, | ||
| 76 | + Integer currentUserLevel) { | ||
| 77 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||
| 78 | + convertSet(members, PmsKnowledgeContentPermissionMemberDO::getUserId)); | ||
| 79 | + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap( | ||
| 80 | + convertSet(members, PmsKnowledgeContentPermissionMemberDO::getDeptId)); | ||
| 81 | + // 拼接 VO 返回 | ||
| 82 | + PmsKnowledgeContentPermissionRespVO permissionVO = BeanUtils.toBean(permission, PmsKnowledgeContentPermissionRespVO.class) | ||
| 83 | + .setCreatorUserId(NumberUtils.parseLong(permission.getCreator())) | ||
| 84 | + .setCurrentUserLevel(currentUserLevel) | ||
| 85 | + .setMembers(BeanUtils.toBean(members, PmsKnowledgeContentPermissionRespVO.Member.class)); | ||
| 86 | + permissionVO.getMembers().forEach(member -> { | ||
| 87 | + findAndThen(userMap, member.getUserId(), user -> member.setUserName(user.getNickname())); | ||
| 88 | + findAndThen(deptMap, member.getDeptId(), dept -> member.setDeptName(dept.getName())); | ||
| 89 | + }); | ||
| 90 | + return permissionVO; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/PmsKnowledgeDocumentController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 7 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document.PmsKnowledgeDocumentCreateReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document.PmsKnowledgeDocumentMoveReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document.PmsKnowledgeDocumentRespVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document.PmsKnowledgeDocumentSearchPageReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document.PmsKnowledgeDocumentUpdateReqVO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.content.PmsKnowledgeDocumentDO; | ||
| 14 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.interaction.PmsKnowledgeDocumentLikeDO; | ||
| 15 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.library.PmsKnowledgeLibraryDO; | ||
| 16 | +import cn.iocoder.yudao.module.pms.enums.kb.content.PmsKnowledgeContentLevelEnum; | ||
| 17 | +import cn.iocoder.yudao.module.pms.enums.kb.content.PmsKnowledgeDocumentTypeEnum; | ||
| 18 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeContentPermissionService; | ||
| 19 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeDocumentService; | ||
| 20 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeDocumentLikeService; | ||
| 21 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeFavoriteService; | ||
| 22 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeViewRecordService; | ||
| 23 | +import cn.iocoder.yudao.module.pms.service.kb.library.PmsKnowledgeLibraryService; | ||
| 24 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 25 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 26 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 27 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 28 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 29 | +import jakarta.annotation.Resource; | ||
| 30 | +import jakarta.validation.Valid; | ||
| 31 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 32 | +import org.springframework.validation.annotation.Validated; | ||
| 33 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 34 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 35 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 36 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 37 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 38 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 39 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 40 | +import org.springframework.web.bind.annotation.RestController; | ||
| 41 | + | ||
| 42 | +import java.util.Collections; | ||
| 43 | +import java.util.List; | ||
| 44 | +import java.util.Map; | ||
| 45 | +import java.util.Set; | ||
| 46 | + | ||
| 47 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 48 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 49 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 50 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 51 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 52 | + | ||
| 53 | +@Tag(name = "管理后台 - PMS 知识库文档") | ||
| 54 | +@RestController | ||
| 55 | +@RequestMapping("/pms/kb/document") | ||
| 56 | +@Validated | ||
| 57 | +public class PmsKnowledgeDocumentController { | ||
| 58 | + | ||
| 59 | + @Resource | ||
| 60 | + private PmsKnowledgeDocumentService documentService; | ||
| 61 | + @Resource | ||
| 62 | + private PmsKnowledgeContentPermissionService contentPermissionService; | ||
| 63 | + @Resource | ||
| 64 | + private PmsKnowledgeFavoriteService favoriteService; | ||
| 65 | + @Resource | ||
| 66 | + private PmsKnowledgeDocumentLikeService documentLikeService; | ||
| 67 | + @Resource | ||
| 68 | + private PmsKnowledgeViewRecordService viewRecordService; | ||
| 69 | + @Resource | ||
| 70 | + private PmsKnowledgeLibraryService libraryService; | ||
| 71 | + | ||
| 72 | + @Resource | ||
| 73 | + private AdminUserApi adminUserApi; | ||
| 74 | + | ||
| 75 | + @PostMapping("/create") | ||
| 76 | + @Operation(summary = "创建文档") | ||
| 77 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 78 | + public CommonResult<Long> createDocument(@Valid @RequestBody PmsKnowledgeDocumentCreateReqVO createReqVO) { | ||
| 79 | + return success(documentService.createDocument(createReqVO, getLoginUserId())); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + @PutMapping("/update") | ||
| 83 | + @Operation(summary = "更新文档内容") | ||
| 84 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 85 | + public CommonResult<Boolean> updateDocument(@Valid @RequestBody PmsKnowledgeDocumentUpdateReqVO updateReqVO) { | ||
| 86 | + documentService.updateDocument(updateReqVO, getLoginUserId()); | ||
| 87 | + return success(true); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + @DeleteMapping("/delete") | ||
| 91 | + @Operation(summary = "将文档移入回收站") | ||
| 92 | + @Parameter(name = "id", description = "文档编号", required = true, example = "1024") | ||
| 93 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 94 | + public CommonResult<Boolean> deleteDocument(@RequestParam("id") Long id) { | ||
| 95 | + documentService.deleteDocument(id, getLoginUserId()); | ||
| 96 | + return success(true); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + @PutMapping("/move") | ||
| 100 | + @Operation(summary = "移动文档") | ||
| 101 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 102 | + public CommonResult<Boolean> moveDocument(@Valid @RequestBody PmsKnowledgeDocumentMoveReqVO moveReqVO) { | ||
| 103 | + documentService.moveDocument(moveReqVO, getLoginUserId()); | ||
| 104 | + return success(true); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + @GetMapping("/get") | ||
| 108 | + @Operation(summary = "获得文档详情") | ||
| 109 | + @Parameter(name = "id", description = "文档编号", required = true, example = "1024") | ||
| 110 | + @Parameter(name = "view", description = "是否记录本次浏览", example = "true") | ||
| 111 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 112 | + public CommonResult<PmsKnowledgeDocumentRespVO> getDocument( | ||
| 113 | + @RequestParam("id") Long id, | ||
| 114 | + @RequestParam(value = "view", defaultValue = "false") Boolean view) { | ||
| 115 | + // 查询文档 | ||
| 116 | + Long userId = getLoginUserId(); | ||
| 117 | + PmsKnowledgeDocumentDO document = documentService.getDocument(id, userId); | ||
| 118 | + // 记录浏览 | ||
| 119 | + if (Boolean.TRUE.equals(view)) { | ||
| 120 | + viewRecordService.createViewRecord(document.getLibraryId(), document.getType(), document.getId(), userId); | ||
| 121 | + } | ||
| 122 | + // 构建文档 VO | ||
| 123 | + return success(buildDocumentRespVO(document, userId)); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + @GetMapping("/search-page") | ||
| 127 | + @Operation(summary = "使用 MySQL 全局搜索文档") | ||
| 128 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 129 | + public CommonResult<PageResult<PmsKnowledgeDocumentRespVO>> getDocumentSearchPage( | ||
| 130 | + @Valid PmsKnowledgeDocumentSearchPageReqVO pageReqVO) { | ||
| 131 | + PageResult<PmsKnowledgeDocumentDO> pageResult = documentService.getDocumentSearchPage( | ||
| 132 | + pageReqVO, getLoginUserId()); | ||
| 133 | + return success(new PageResult<>(buildDocumentRespVOList(pageResult.getList()), pageResult.getTotal())); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + // ==================== 拼接 VO ==================== | ||
| 137 | + | ||
| 138 | + private PmsKnowledgeDocumentRespVO buildDocumentRespVO(PmsKnowledgeDocumentDO document, Long userId) { | ||
| 139 | + // 1.1 拼接当前用户的内容权限和互动状态 | ||
| 140 | + Integer currentUserLevel = contentPermissionService.getCurrentUserContentPermissionLevel( | ||
| 141 | + document.getPermissionId(), document.getLibraryId(), userId); | ||
| 142 | + Long creatorUserId = NumberUtils.parseLong(document.getCreator()); | ||
| 143 | + PmsKnowledgeDocumentRespVO documentVO = BeanUtils.toBean(document, PmsKnowledgeDocumentRespVO.class) | ||
| 144 | + .setCreatorUserId(creatorUserId).setCurrentUserLevel(currentUserLevel) | ||
| 145 | + .setDownloadStatus(PmsKnowledgeContentLevelEnum.canDownload(currentUserLevel)) | ||
| 146 | + .setPreviewUrl(document.getContent()) | ||
| 147 | + .setFavoriteStatus(favoriteService.isFavorite(document.getType(), document.getId(), userId)); | ||
| 148 | + // 1.2 文件不可下载时,隐藏实际文件地址 | ||
| 149 | + if (PmsKnowledgeDocumentTypeEnum.FILE.getType().equals(document.getType()) | ||
| 150 | + && Boolean.FALSE.equals(documentVO.getDownloadStatus())) { | ||
| 151 | + documentVO.setContent(null); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + // 2. 一次查询并拼接创建人和点赞用户信息 | ||
| 155 | + List<PmsKnowledgeDocumentLikeDO> likes = documentLikeService.getDocumentLikeList(document.getId()); | ||
| 156 | + Set<Long> relatedUserIds = convertSet(likes, PmsKnowledgeDocumentLikeDO::getUserId); | ||
| 157 | + relatedUserIds.add(creatorUserId); | ||
| 158 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(relatedUserIds); | ||
| 159 | + findAndThen(userMap, creatorUserId, user -> documentVO.setCreatorUserName(user.getNickname())); | ||
| 160 | + documentVO.setLikeStatus(CollUtil.anyMatch(likes, like -> userId.equals(like.getUserId()))) | ||
| 161 | + .setLikeUsers(convertList(likes, like -> { | ||
| 162 | + PmsKnowledgeDocumentRespVO.LikeUser likeUser = new PmsKnowledgeDocumentRespVO.LikeUser() | ||
| 163 | + .setId(like.getUserId()); | ||
| 164 | + findAndThen(userMap, like.getUserId(), user -> | ||
| 165 | + likeUser.setNickname(user.getNickname()).setAvatar(user.getAvatar())); | ||
| 166 | + return likeUser; | ||
| 167 | + })); | ||
| 168 | + return documentVO; | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + private List<PmsKnowledgeDocumentRespVO> buildDocumentRespVOList(List<PmsKnowledgeDocumentDO> documents) { | ||
| 172 | + if (CollUtil.isEmpty(documents)) { | ||
| 173 | + return Collections.emptyList(); | ||
| 174 | + } | ||
| 175 | + Map<Long, PmsKnowledgeLibraryDO> libraryMap = libraryService.getLibraryMap( | ||
| 176 | + convertSet(documents, PmsKnowledgeDocumentDO::getLibraryId)); | ||
| 177 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(documents, | ||
| 178 | + document -> NumberUtils.parseLong(document.getCreator()))); | ||
| 179 | + return convertList(documents, document -> { | ||
| 180 | + PmsKnowledgeDocumentRespVO documentVO = BeanUtils.toBean(document, PmsKnowledgeDocumentRespVO.class) | ||
| 181 | + .setContent(null).setContentSummary(buildContentSummary(document.getContent())) | ||
| 182 | + .setCreatorUserId(NumberUtils.parseLong(document.getCreator())); | ||
| 183 | + findAndThen(libraryMap, document.getLibraryId(), | ||
| 184 | + library -> documentVO.setLibraryName(library.getName())); | ||
| 185 | + findAndThen(userMap, documentVO.getCreatorUserId(), | ||
| 186 | + user -> documentVO.setCreatorUserName(user.getNickname())); | ||
| 187 | + return documentVO; | ||
| 188 | + }); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + /** | ||
| 192 | + * 构造搜索结果摘要,避免直接返回完整正文 | ||
| 193 | + */ | ||
| 194 | + private String buildContentSummary(String content) { | ||
| 195 | + if (content == null || content.trim().isEmpty()) { | ||
| 196 | + return null; | ||
| 197 | + } | ||
| 198 | + String summary = content.replaceAll("<[^>]+>", " ").replaceAll("\\s+", " ").trim(); | ||
| 199 | + return summary.length() > 120 ? summary.substring(0, 120) + "…" : summary; | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/PmsKnowledgeDocumentLabelController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 7 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document.PmsKnowledgeDocumentRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.label.PmsKnowledgeDocumentLabelPageReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.label.PmsKnowledgeDocumentLabelRespVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.label.PmsKnowledgeDocumentLabelSaveReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.content.PmsKnowledgeDocumentDO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.library.PmsKnowledgeLibraryDO; | ||
| 14 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeDocumentLabelService; | ||
| 15 | +import cn.iocoder.yudao.module.pms.service.kb.library.PmsKnowledgeLibraryService; | ||
| 16 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 17 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 18 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 19 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 20 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 21 | +import jakarta.annotation.Resource; | ||
| 22 | +import jakarta.validation.Valid; | ||
| 23 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 24 | +import org.springframework.validation.annotation.Validated; | ||
| 25 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 27 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 28 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 29 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 30 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 31 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 32 | +import org.springframework.web.bind.annotation.RestController; | ||
| 33 | + | ||
| 34 | +import java.util.Collections; | ||
| 35 | +import java.util.List; | ||
| 36 | +import java.util.Map; | ||
| 37 | + | ||
| 38 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 39 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 40 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 41 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 42 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 43 | + | ||
| 44 | +@Tag(name = "管理后台 - PMS 知识库文档标签") | ||
| 45 | +@RestController | ||
| 46 | +@RequestMapping("/pms/kb/document-label") | ||
| 47 | +@Validated | ||
| 48 | +public class PmsKnowledgeDocumentLabelController { | ||
| 49 | + | ||
| 50 | + @Resource | ||
| 51 | + private PmsKnowledgeDocumentLabelService documentLabelService; | ||
| 52 | + @Resource | ||
| 53 | + private PmsKnowledgeLibraryService libraryService; | ||
| 54 | + | ||
| 55 | + @Resource | ||
| 56 | + private AdminUserApi adminUserApi; | ||
| 57 | + | ||
| 58 | + @PostMapping("/create") | ||
| 59 | + @Operation(summary = "创建文档标签") | ||
| 60 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 61 | + public CommonResult<Long> createDocumentLabel( | ||
| 62 | + @Valid @RequestBody PmsKnowledgeDocumentLabelSaveReqVO saveReqVO) { | ||
| 63 | + return success(documentLabelService.createDocumentLabel(saveReqVO)); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + @PutMapping("/update") | ||
| 67 | + @Operation(summary = "修改文档标签") | ||
| 68 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 69 | + public CommonResult<Boolean> updateDocumentLabel( | ||
| 70 | + @Valid @RequestBody PmsKnowledgeDocumentLabelSaveReqVO saveReqVO) { | ||
| 71 | + documentLabelService.updateDocumentLabel(saveReqVO); | ||
| 72 | + return success(true); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + @DeleteMapping("/delete") | ||
| 76 | + @Operation(summary = "删除文档标签") | ||
| 77 | + @Parameter(name = "id", description = "文档标签编号", required = true, example = "1024") | ||
| 78 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 79 | + public CommonResult<Boolean> deleteDocumentLabel(@RequestParam("id") Long id) { | ||
| 80 | + documentLabelService.deleteDocumentLabel(id); | ||
| 81 | + return success(true); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + @GetMapping("/get") | ||
| 85 | + @Operation(summary = "获得文档标签详情") | ||
| 86 | + @Parameter(name = "id", description = "文档标签编号", required = true, example = "1024") | ||
| 87 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 88 | + public CommonResult<PmsKnowledgeDocumentLabelRespVO> getDocumentLabel(@RequestParam("id") Long id) { | ||
| 89 | + return success(BeanUtils.toBean(documentLabelService.getDocumentLabel(id), | ||
| 90 | + PmsKnowledgeDocumentLabelRespVO.class)); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + @GetMapping("/list") | ||
| 94 | + @Operation(summary = "获得文档标签列表") | ||
| 95 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 96 | + public CommonResult<List<PmsKnowledgeDocumentLabelRespVO>> getDocumentLabelList() { | ||
| 97 | + return success(BeanUtils.toBean(documentLabelService.getDocumentLabelList(), | ||
| 98 | + PmsKnowledgeDocumentLabelRespVO.class)); | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + @GetMapping("/document-page") | ||
| 102 | + @Operation(summary = "获得指定标签的文档分页") | ||
| 103 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 104 | + public CommonResult<PageResult<PmsKnowledgeDocumentRespVO>> getDocumentPageByLabel( | ||
| 105 | + @Valid PmsKnowledgeDocumentLabelPageReqVO pageReqVO) { | ||
| 106 | + PageResult<PmsKnowledgeDocumentDO> pageResult = documentLabelService.getDocumentPageByLabel( | ||
| 107 | + pageReqVO, getLoginUserId()); | ||
| 108 | + return success(new PageResult<>(buildDocumentRespVOList(pageResult.getList()), pageResult.getTotal())); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + // ==================== 拼接 VO ==================== | ||
| 112 | + | ||
| 113 | + private List<PmsKnowledgeDocumentRespVO> buildDocumentRespVOList(List<PmsKnowledgeDocumentDO> documents) { | ||
| 114 | + if (CollUtil.isEmpty(documents)) { | ||
| 115 | + return Collections.emptyList(); | ||
| 116 | + } | ||
| 117 | + Map<Long, PmsKnowledgeLibraryDO> libraryMap = libraryService.getLibraryMap( | ||
| 118 | + convertSet(documents, PmsKnowledgeDocumentDO::getLibraryId)); | ||
| 119 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(documents, | ||
| 120 | + document -> NumberUtils.parseLong(document.getCreator()))); | ||
| 121 | + return convertList(documents, document -> { | ||
| 122 | + PmsKnowledgeDocumentRespVO documentVO = BeanUtils.toBean(document, PmsKnowledgeDocumentRespVO.class) | ||
| 123 | + .setContent(null).setCreatorUserId(NumberUtils.parseLong(document.getCreator())); | ||
| 124 | + findAndThen(libraryMap, document.getLibraryId(), | ||
| 125 | + library -> documentVO.setLibraryName(library.getName())); | ||
| 126 | + findAndThen(userMap, documentVO.getCreatorUserId(), | ||
| 127 | + user -> documentVO.setCreatorUserName(user.getNickname())); | ||
| 128 | + return documentVO; | ||
| 129 | + }); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/PmsKnowledgeFolderController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.folder.PmsKnowledgeFolderMoveReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.folder.PmsKnowledgeFolderRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.folder.PmsKnowledgeFolderSaveReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.folder.PmsKnowledgeTreeRespVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.content.PmsKnowledgeDocumentDO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.content.PmsKnowledgeFolderDO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.enums.kb.PmsKnowledgeObjectTypeEnum; | ||
| 13 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeContentPermissionService; | ||
| 14 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeDocumentService; | ||
| 15 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeFolderService; | ||
| 16 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeFavoriteService; | ||
| 17 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeViewRecordService; | ||
| 18 | +import cn.iocoder.yudao.module.pms.service.kb.library.PmsKnowledgeLibraryMemberService; | ||
| 19 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 20 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 21 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 22 | +import jakarta.annotation.Resource; | ||
| 23 | +import jakarta.validation.Valid; | ||
| 24 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 25 | +import org.springframework.validation.annotation.Validated; | ||
| 26 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 27 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 28 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 29 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 30 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 31 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 32 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 33 | +import org.springframework.web.bind.annotation.RestController; | ||
| 34 | + | ||
| 35 | +import java.util.ArrayList; | ||
| 36 | +import java.util.List; | ||
| 37 | +import java.util.Map; | ||
| 38 | +import java.util.Set; | ||
| 39 | + | ||
| 40 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 41 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 42 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 43 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 44 | + | ||
| 45 | +@Tag(name = "管理后台 - PMS 知识库文件夹") | ||
| 46 | +@RestController | ||
| 47 | +@RequestMapping("/pms/kb/folder") | ||
| 48 | +@Validated | ||
| 49 | +public class PmsKnowledgeFolderController { | ||
| 50 | + | ||
| 51 | + @Resource | ||
| 52 | + private PmsKnowledgeFolderService folderService; | ||
| 53 | + @Resource | ||
| 54 | + private PmsKnowledgeDocumentService documentService; | ||
| 55 | + @Resource | ||
| 56 | + private PmsKnowledgeContentPermissionService contentPermissionService; | ||
| 57 | + @Resource | ||
| 58 | + private PmsKnowledgeLibraryMemberService libraryMemberService; | ||
| 59 | + @Resource | ||
| 60 | + private PmsKnowledgeFavoriteService favoriteService; | ||
| 61 | + @Resource | ||
| 62 | + private PmsKnowledgeViewRecordService viewRecordService; | ||
| 63 | + | ||
| 64 | + @PostMapping("/create") | ||
| 65 | + @Operation(summary = "创建文件夹") | ||
| 66 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 67 | + public CommonResult<Long> createFolder(@Valid @RequestBody PmsKnowledgeFolderSaveReqVO saveReqVO) { | ||
| 68 | + return success(folderService.createFolder(saveReqVO, getLoginUserId())); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + @PutMapping("/update") | ||
| 72 | + @Operation(summary = "更新文件夹") | ||
| 73 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 74 | + public CommonResult<Boolean> updateFolder(@Valid @RequestBody PmsKnowledgeFolderSaveReqVO saveReqVO) { | ||
| 75 | + folderService.updateFolder(saveReqVO, getLoginUserId()); | ||
| 76 | + return success(true); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + @DeleteMapping("/delete") | ||
| 80 | + @Operation(summary = "将文件夹移入回收站") | ||
| 81 | + @Parameter(name = "id", description = "文件夹编号", required = true, example = "1024") | ||
| 82 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 83 | + public CommonResult<Boolean> deleteFolder(@RequestParam("id") Long id) { | ||
| 84 | + folderService.deleteFolder(id, getLoginUserId()); | ||
| 85 | + return success(true); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + @PutMapping("/move") | ||
| 89 | + @Operation(summary = "移动文件夹") | ||
| 90 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 91 | + public CommonResult<Boolean> moveFolder(@Valid @RequestBody PmsKnowledgeFolderMoveReqVO moveReqVO) { | ||
| 92 | + folderService.moveFolder(moveReqVO, getLoginUserId()); | ||
| 93 | + return success(true); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + @GetMapping("/get") | ||
| 97 | + @Operation(summary = "获得文件夹详情") | ||
| 98 | + @Parameter(name = "id", description = "文件夹编号", required = true, example = "1024") | ||
| 99 | + @Parameter(name = "view", description = "是否记录本次浏览", example = "true") | ||
| 100 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 101 | + public CommonResult<PmsKnowledgeFolderRespVO> getFolder( | ||
| 102 | + @RequestParam("id") Long id, | ||
| 103 | + @RequestParam(value = "view", defaultValue = "false") Boolean view) { | ||
| 104 | + Long userId = getLoginUserId(); | ||
| 105 | + PmsKnowledgeFolderDO folder = folderService.getFolder(id, userId); | ||
| 106 | + if (Boolean.TRUE.equals(view)) { | ||
| 107 | + viewRecordService.createViewRecord(folder.getLibraryId(), PmsKnowledgeObjectTypeEnum.FOLDER.getType(), | ||
| 108 | + folder.getId(), userId); | ||
| 109 | + } | ||
| 110 | + return success(buildFolderRespVO(folder, userId)); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + @GetMapping("/tree") | ||
| 114 | + @Operation(summary = "获得知识库目录树") | ||
| 115 | + @Parameter(name = "libraryId", description = "知识库编号", required = true, example = "1024") | ||
| 116 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 117 | + public CommonResult<PmsKnowledgeTreeRespVO> getFolderTree(@RequestParam("libraryId") Long libraryId) { | ||
| 118 | + Long userId = getLoginUserId(); | ||
| 119 | + List<PmsKnowledgeFolderDO> folders = folderService.getFolderList(libraryId, userId); | ||
| 120 | + List<PmsKnowledgeDocumentDO> documents = documentService.getDocumentList(libraryId, userId); | ||
| 121 | + return success(buildTreeRespVO(libraryId, userId, | ||
| 122 | + libraryMemberService.isLibraryWritable(libraryId, userId), | ||
| 123 | + libraryMemberService.isLibraryAdmin(libraryId, userId), folders, documents)); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + // ==================== 拼接 VO ==================== | ||
| 127 | + | ||
| 128 | + private PmsKnowledgeFolderRespVO buildFolderRespVO(PmsKnowledgeFolderDO folder, Long userId) { | ||
| 129 | + List<PmsKnowledgeFolderDO> folders = folderService.getFolderList(folder.getLibraryId(), userId); | ||
| 130 | + List<PmsKnowledgeDocumentDO> documents = documentService.getDocumentList(folder.getLibraryId(), userId); | ||
| 131 | + int childFolderCount = CollUtil.count(folders, | ||
| 132 | + item -> folder.getId().equals(item.getParentId())); | ||
| 133 | + int documentCount = (int) CollUtil.count(documents, | ||
| 134 | + item -> folder.getId().equals(item.getFolderId()) | ||
| 135 | + && (item.getParentId() == null || item.getParentId() == 0L)); | ||
| 136 | + return BeanUtils.toBean(folder, PmsKnowledgeFolderRespVO.class) | ||
| 137 | + .setChildFolderCount(childFolderCount).setDocumentCount(documentCount) | ||
| 138 | + .setCurrentUserLevel(contentPermissionService.getCurrentUserContentPermissionLevel(folder.getPermissionId(), folder.getLibraryId(), userId)) | ||
| 139 | + .setFavoriteStatus(favoriteService.isFavorite(PmsKnowledgeObjectTypeEnum.FOLDER.getType(), folder.getId(), userId)); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + private PmsKnowledgeTreeRespVO buildTreeRespVO(Long libraryId, Long userId, boolean writeStatus, | ||
| 143 | + boolean manageStatus, | ||
| 144 | + List<PmsKnowledgeFolderDO> folders, List<PmsKnowledgeDocumentDO> documents) { | ||
| 145 | + // 1. 批量获得当前用户的内容权限等级 | ||
| 146 | + Set<Long> permissionIds = convertSet(folders, PmsKnowledgeFolderDO::getPermissionId); | ||
| 147 | + permissionIds.addAll(convertSet(documents, PmsKnowledgeDocumentDO::getPermissionId)); | ||
| 148 | + Map<Long, Integer> levelMap = contentPermissionService.getCurrentUserContentPermissionLevelMap(permissionIds, libraryId, userId); | ||
| 149 | + | ||
| 150 | + // 2. 批量转换文件夹和文档节点 | ||
| 151 | + Map<Long, PmsKnowledgeTreeRespVO.FolderNode> folderNodeMap = convertMap(folders, | ||
| 152 | + PmsKnowledgeFolderDO::getId, folder -> BeanUtils.toBean(folder, PmsKnowledgeTreeRespVO.FolderNode.class) | ||
| 153 | + .setCurrentUserLevel(levelMap.get(folder.getPermissionId())).setChildren(new ArrayList<>()).setDocuments(new ArrayList<>())); | ||
| 154 | + Map<Long, PmsKnowledgeTreeRespVO.DocumentNode> documentNodeMap = convertMap(documents, | ||
| 155 | + PmsKnowledgeDocumentDO::getId, document -> BeanUtils.toBean(document, PmsKnowledgeTreeRespVO.DocumentNode.class) | ||
| 156 | + .setCurrentUserLevel(levelMap.get(document.getPermissionId())).setChildren(new ArrayList<>())); | ||
| 157 | + | ||
| 158 | + // 3. 按父文档或所属文件夹组装文档树 | ||
| 159 | + List<PmsKnowledgeTreeRespVO.DocumentNode> rootDocuments = new ArrayList<>(); | ||
| 160 | + for (PmsKnowledgeDocumentDO document : documents) { | ||
| 161 | + PmsKnowledgeTreeRespVO.DocumentNode node = documentNodeMap.get(document.getId()); | ||
| 162 | + PmsKnowledgeTreeRespVO.DocumentNode parentNode = documentNodeMap.get(document.getParentId()); | ||
| 163 | + PmsKnowledgeTreeRespVO.FolderNode folderNode = folderNodeMap.get(document.getFolderId()); | ||
| 164 | + if (parentNode != null) { | ||
| 165 | + parentNode.getChildren().add(node); | ||
| 166 | + } else if (folderNode != null) { | ||
| 167 | + folderNode.getDocuments().add(node); | ||
| 168 | + } else { | ||
| 169 | + rootDocuments.add(node); | ||
| 170 | + } | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + // 4. 按父文件夹组装文件夹树 | ||
| 174 | + List<PmsKnowledgeTreeRespVO.FolderNode> rootFolders = new ArrayList<>(); | ||
| 175 | + for (PmsKnowledgeFolderDO folder : folders) { | ||
| 176 | + PmsKnowledgeTreeRespVO.FolderNode node = folderNodeMap.get(folder.getId()); | ||
| 177 | + PmsKnowledgeTreeRespVO.FolderNode parentNode = folderNodeMap.get(folder.getParentId()); | ||
| 178 | + if (parentNode != null) { | ||
| 179 | + parentNode.getChildren().add(node); | ||
| 180 | + } else { | ||
| 181 | + rootFolders.add(node); | ||
| 182 | + } | ||
| 183 | + } | ||
| 184 | + return new PmsKnowledgeTreeRespVO().setLibraryId(libraryId).setWriteStatus(writeStatus) | ||
| 185 | + .setManageStatus(manageStatus) | ||
| 186 | + .setFolders(rootFolders).setDocuments(rootDocuments); | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/document/PmsKnowledgeDocumentCreateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 4 | +import cn.iocoder.yudao.module.pms.enums.kb.content.PmsKnowledgeDocumentTypeEnum; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import jakarta.validation.constraints.Max; | ||
| 7 | +import jakarta.validation.constraints.Min; | ||
| 8 | +import jakarta.validation.constraints.NotBlank; | ||
| 9 | +import jakarta.validation.constraints.NotNull; | ||
| 10 | +import jakarta.validation.constraints.Size; | ||
| 11 | +import lombok.Data; | ||
| 12 | + | ||
| 13 | +@Schema(description = "管理后台 - PMS 知识库文档新增 Request VO") | ||
| 14 | +@Data | ||
| 15 | +public class PmsKnowledgeDocumentCreateReqVO { | ||
| 16 | + | ||
| 17 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 18 | + @NotNull(message = "知识库编号不能为空") | ||
| 19 | + private Long libraryId; | ||
| 20 | + | ||
| 21 | + @Schema(description = "文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 22 | + @NotNull(message = "文件夹编号不能为空") | ||
| 23 | + private Long folderId; | ||
| 24 | + | ||
| 25 | + @Schema(description = "父文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 26 | + @NotNull(message = "父文档编号不能为空") | ||
| 27 | + private Long parentId; | ||
| 28 | + | ||
| 29 | + @Schema(description = "文档标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品说明") | ||
| 30 | + @NotBlank(message = "文档标题不能为空") | ||
| 31 | + @Size(max = 255, message = "文档标题不能超过 255 个字符") | ||
| 32 | + private String title; | ||
| 33 | + | ||
| 34 | + @Schema(description = "文档类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 35 | + @NotNull(message = "文档类型不能为空") | ||
| 36 | + @InEnum(PmsKnowledgeDocumentTypeEnum.class) | ||
| 37 | + private Integer type; | ||
| 38 | + | ||
| 39 | + @Schema(description = "文档内容或文件地址") | ||
| 40 | + private String content; | ||
| 41 | + | ||
| 42 | + @Schema(description = "文件类型", example = "pdf") | ||
| 43 | + @Size(max = 50, message = "文件类型不能超过 50 个字符") | ||
| 44 | + private String fileType; | ||
| 45 | + | ||
| 46 | + @Schema(description = "文件大小,单位:字节", example = "102400") | ||
| 47 | + @Min(value = 0, message = "文件大小不能小于 0") | ||
| 48 | + @Max(value = 104857600, message = "文件大小不能超过 100 MB") | ||
| 49 | + private Long fileSize; | ||
| 50 | + | ||
| 51 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/document/PmsKnowledgeDocumentMoveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - PMS 知识库文档移动 Request VO") | ||
| 8 | +@Data | ||
| 9 | +public class PmsKnowledgeDocumentMoveReqVO { | ||
| 10 | + | ||
| 11 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 12 | + @NotNull(message = "文档编号不能为空") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "目标知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 16 | + @NotNull(message = "目标知识库编号不能为空") | ||
| 17 | + private Long targetLibraryId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "目标文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 20 | + @NotNull(message = "目标文件夹编号不能为空") | ||
| 21 | + private Long targetFolderId; | ||
| 22 | + | ||
| 23 | + @Schema(description = "目标父文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 24 | + @NotNull(message = "目标父文档编号不能为空") | ||
| 25 | + private Long targetParentId; | ||
| 26 | + | ||
| 27 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/document/PmsKnowledgeDocumentRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库文档 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeDocumentRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + private Long libraryId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "协作权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 20 | + private Long permissionId; | ||
| 21 | + | ||
| 22 | + @Schema(description = "当前用户协作等级", example = "3") | ||
| 23 | + private Integer currentUserLevel; | ||
| 24 | + | ||
| 25 | + @Schema(description = "当前用户是否可下载", example = "true") | ||
| 26 | + private Boolean downloadStatus; | ||
| 27 | + | ||
| 28 | + @Schema(description = "知识库名称", example = "产品知识库") | ||
| 29 | + private String libraryName; | ||
| 30 | + | ||
| 31 | + @Schema(description = "文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 32 | + private Long folderId; | ||
| 33 | + | ||
| 34 | + @Schema(description = "父文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 35 | + private Long parentId; | ||
| 36 | + | ||
| 37 | + @Schema(description = "文档标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品说明") | ||
| 38 | + private String title; | ||
| 39 | + | ||
| 40 | + @Schema(description = "正文摘要") | ||
| 41 | + private String contentSummary; | ||
| 42 | + | ||
| 43 | + @Schema(description = "文档内容或文件地址") | ||
| 44 | + private String content; | ||
| 45 | + | ||
| 46 | + @Schema(description = "文件预览地址(下载权限不足时仍可用于在线预览)") | ||
| 47 | + private String previewUrl; | ||
| 48 | + | ||
| 49 | + @Schema(description = "文档类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 50 | + private Integer type; | ||
| 51 | + | ||
| 52 | + @Schema(description = "文件类型", example = "pdf") | ||
| 53 | + private String fileType; | ||
| 54 | + | ||
| 55 | + @Schema(description = "文件大小,单位:字节", example = "102400") | ||
| 56 | + private Long fileSize; | ||
| 57 | + | ||
| 58 | + @Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 59 | + private Integer status; | ||
| 60 | + | ||
| 61 | + @Schema(description = "标签编号列表", example = "[1024, 2048]") | ||
| 62 | + private List<Long> labelIds; | ||
| 63 | + | ||
| 64 | + @Schema(description = "创建人用户编号", example = "1") | ||
| 65 | + private Long creatorUserId; | ||
| 66 | + | ||
| 67 | + @Schema(description = "创建人姓名", example = "芋道") | ||
| 68 | + private String creatorUserName; | ||
| 69 | + | ||
| 70 | + @Schema(description = "当前用户是否已关注") | ||
| 71 | + private Boolean favoriteStatus; | ||
| 72 | + | ||
| 73 | + @Schema(description = "当前用户是否已点赞") | ||
| 74 | + private Boolean likeStatus; | ||
| 75 | + | ||
| 76 | + @Schema(description = "点赞用户列表") | ||
| 77 | + private List<LikeUser> likeUsers; | ||
| 78 | + | ||
| 79 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 80 | + private LocalDateTime createTime; | ||
| 81 | + | ||
| 82 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 83 | + private LocalDateTime updateTime; | ||
| 84 | + | ||
| 85 | + @Schema(description = "管理后台 - PMS 知识文档点赞用户 Response VO") | ||
| 86 | + @Data | ||
| 87 | + public static class LikeUser { | ||
| 88 | + | ||
| 89 | + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 90 | + private Long id; | ||
| 91 | + | ||
| 92 | + @Schema(description = "用户昵称", example = "芋道") | ||
| 93 | + private String nickname; | ||
| 94 | + | ||
| 95 | + @Schema(description = "用户头像") | ||
| 96 | + private String avatar; | ||
| 97 | + | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/document/PmsKnowledgeDocumentSearchPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 9 | + | ||
| 10 | +import java.time.LocalDateTime; | ||
| 11 | + | ||
| 12 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 13 | + | ||
| 14 | +@Schema(description = "管理后台 - PMS 知识库文档全局搜索分页 Request VO") | ||
| 15 | +@Data | ||
| 16 | +@EqualsAndHashCode(callSuper = true) | ||
| 17 | +@ToString(callSuper = true) | ||
| 18 | +public class PmsKnowledgeDocumentSearchPageReqVO extends PageParam { | ||
| 19 | + | ||
| 20 | + @Schema(description = "搜索关键字", example = "产品方案") | ||
| 21 | + private String keyword; | ||
| 22 | + | ||
| 23 | + @Schema(description = "知识库编号", example = "1024") | ||
| 24 | + private Long libraryId; | ||
| 25 | + | ||
| 26 | + @Schema(description = "创建人用户编号", example = "1") | ||
| 27 | + private Long creatorUserId; | ||
| 28 | + | ||
| 29 | + @Schema(description = "更新时间范围") | ||
| 30 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 31 | + private LocalDateTime[] updateTime; | ||
| 32 | + | ||
| 33 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/document/PmsKnowledgeDocumentUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.document; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.Max; | ||
| 5 | +import jakarta.validation.constraints.Min; | ||
| 6 | +import jakarta.validation.constraints.NotNull; | ||
| 7 | +import jakarta.validation.constraints.Size; | ||
| 8 | +import lombok.Data; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +@Schema(description = "管理后台 - PMS 知识库文档修改 Request VO") | ||
| 13 | +@Data | ||
| 14 | +public class PmsKnowledgeDocumentUpdateReqVO { | ||
| 15 | + | ||
| 16 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + @NotNull(message = "文档编号不能为空") | ||
| 18 | + private Long id; | ||
| 19 | + | ||
| 20 | + @Schema(description = "文档标题", example = "产品说明") | ||
| 21 | + @Size(max = 255, message = "文档标题不能超过 255 个字符") | ||
| 22 | + private String title; | ||
| 23 | + | ||
| 24 | + @Schema(description = "文档内容或文件地址") | ||
| 25 | + private String content; | ||
| 26 | + | ||
| 27 | + @Schema(description = "标签编号列表;传空集合表示清空标签") | ||
| 28 | + private List<Long> labelIds; | ||
| 29 | + | ||
| 30 | + @Schema(description = "文件类型", example = "pdf") | ||
| 31 | + @Size(max = 50, message = "文件类型不能超过 50 个字符") | ||
| 32 | + private String fileType; | ||
| 33 | + | ||
| 34 | + @Schema(description = "文件大小,单位:字节", example = "102400") | ||
| 35 | + @Min(value = 0, message = "文件大小不能小于 0") | ||
| 36 | + @Max(value = 104857600, message = "文件大小不能超过 100 MB") | ||
| 37 | + private Long fileSize; | ||
| 38 | + | ||
| 39 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/folder/PmsKnowledgeFolderMoveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.folder; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - PMS 知识库文件夹移动 Request VO") | ||
| 8 | +@Data | ||
| 9 | +public class PmsKnowledgeFolderMoveReqVO { | ||
| 10 | + | ||
| 11 | + @Schema(description = "文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 12 | + @NotNull(message = "文件夹编号不能为空") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "目标知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 16 | + @NotNull(message = "目标知识库编号不能为空") | ||
| 17 | + private Long targetLibraryId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "目标父文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 20 | + @NotNull(message = "目标父文件夹编号不能为空") | ||
| 21 | + private Long targetParentId; | ||
| 22 | + | ||
| 23 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/folder/PmsKnowledgeFolderRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.folder; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识库文件夹 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeFolderRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 16 | + private Long libraryId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "协作权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 19 | + private Long permissionId; | ||
| 20 | + | ||
| 21 | + @Schema(description = "当前用户协作等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 22 | + private Integer currentUserLevel; | ||
| 23 | + | ||
| 24 | + @Schema(description = "父文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 25 | + private Long parentId; | ||
| 26 | + | ||
| 27 | + @Schema(description = "文件夹标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品文档") | ||
| 28 | + private String title; | ||
| 29 | + | ||
| 30 | + @Schema(description = "直属子文件夹数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 31 | + private Integer childFolderCount; | ||
| 32 | + | ||
| 33 | + @Schema(description = "直属文档数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12") | ||
| 34 | + private Integer documentCount; | ||
| 35 | + | ||
| 36 | + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 37 | + private Integer status; | ||
| 38 | + | ||
| 39 | + @Schema(description = "当前用户是否已关注", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 40 | + private Boolean favoriteStatus; | ||
| 41 | + | ||
| 42 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 43 | + private LocalDateTime createTime; | ||
| 44 | + | ||
| 45 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 46 | + private LocalDateTime updateTime; | ||
| 47 | + | ||
| 48 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/folder/PmsKnowledgeFolderSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.folder; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 6 | +import jakarta.validation.constraints.Size; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库文件夹新增/修改 Request VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeFolderSaveReqVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "文件夹编号", example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + @NotNull(message = "知识库编号不能为空") | ||
| 18 | + private Long libraryId; | ||
| 19 | + | ||
| 20 | + @Schema(description = "父文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 21 | + @NotNull(message = "父文件夹编号不能为空") | ||
| 22 | + private Long parentId; | ||
| 23 | + | ||
| 24 | + @Schema(description = "文件夹标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品文档") | ||
| 25 | + @NotBlank(message = "文件夹标题不能为空") | ||
| 26 | + @Size(max = 255, message = "文件夹标题不能超过 255 个字符") | ||
| 27 | + private String title; | ||
| 28 | + | ||
| 29 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/folder/PmsKnowledgeTreeRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.folder; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.util.List; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识库目录树 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeTreeRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long libraryId; | ||
| 14 | + | ||
| 15 | + @Schema(description = "当前用户是否可编辑", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 16 | + private Boolean writeStatus; | ||
| 17 | + | ||
| 18 | + @Schema(description = "当前用户是否可管理目录结构", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 19 | + private Boolean manageStatus; | ||
| 20 | + | ||
| 21 | + @Schema(description = "根文件夹列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 22 | + private List<FolderNode> folders; | ||
| 23 | + | ||
| 24 | + @Schema(description = "根文档列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 25 | + private List<DocumentNode> documents; | ||
| 26 | + | ||
| 27 | + @Schema(description = "管理后台 - PMS 知识库文件夹树节点 Response VO") | ||
| 28 | + @Data | ||
| 29 | + public static class FolderNode { | ||
| 30 | + | ||
| 31 | + @Schema(description = "文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 32 | + private Long id; | ||
| 33 | + | ||
| 34 | + @Schema(description = "协作权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 35 | + private Long permissionId; | ||
| 36 | + | ||
| 37 | + @Schema(description = "当前用户协作等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 38 | + private Integer currentUserLevel; | ||
| 39 | + | ||
| 40 | + @Schema(description = "父文件夹编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 41 | + private Long parentId; | ||
| 42 | + | ||
| 43 | + @Schema(description = "文件夹标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品文档") | ||
| 44 | + private String title; | ||
| 45 | + | ||
| 46 | + @Schema(description = "子文件夹列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 47 | + private List<FolderNode> children; | ||
| 48 | + | ||
| 49 | + @Schema(description = "文件夹下的文档列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 50 | + private List<DocumentNode> documents; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + @Schema(description = "管理后台 - PMS 知识库文档树节点 Response VO") | ||
| 54 | + @Data | ||
| 55 | + public static class DocumentNode { | ||
| 56 | + | ||
| 57 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 58 | + private Long id; | ||
| 59 | + | ||
| 60 | + @Schema(description = "协作权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 61 | + private Long permissionId; | ||
| 62 | + | ||
| 63 | + @Schema(description = "当前用户协作等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 64 | + private Integer currentUserLevel; | ||
| 65 | + | ||
| 66 | + @Schema(description = "父文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 67 | + private Long parentId; | ||
| 68 | + | ||
| 69 | + @Schema(description = "文档标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品说明") | ||
| 70 | + private String title; | ||
| 71 | + | ||
| 72 | + @Schema(description = "文档类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 73 | + private Integer type; | ||
| 74 | + | ||
| 75 | + @Schema(description = "文件类型", example = "pdf") | ||
| 76 | + private String fileType; | ||
| 77 | + | ||
| 78 | + @Schema(description = "子文档列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 79 | + private List<DocumentNode> children; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/label/PmsKnowledgeDocumentLabelPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.label; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.ToString; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - PMS 按标签查询文档分页 Request VO") | ||
| 11 | +@Data | ||
| 12 | +@EqualsAndHashCode(callSuper = true) | ||
| 13 | +@ToString(callSuper = true) | ||
| 14 | +public class PmsKnowledgeDocumentLabelPageReqVO extends PageParam { | ||
| 15 | + | ||
| 16 | + @Schema(description = "文档标签编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + @NotNull(message = "文档标签编号不能为空") | ||
| 18 | + private Long labelId; | ||
| 19 | + | ||
| 20 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/label/PmsKnowledgeDocumentLabelRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.label; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识库文档标签 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeDocumentLabelRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "文档标签编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "标签名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品") | ||
| 16 | + private String name; | ||
| 17 | + | ||
| 18 | + @Schema(description = "标签颜色", requiredMode = Schema.RequiredMode.REQUIRED, example = "#409EFF") | ||
| 19 | + private String color; | ||
| 20 | + | ||
| 21 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 22 | + private LocalDateTime createTime; | ||
| 23 | + | ||
| 24 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/label/PmsKnowledgeDocumentLabelSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.label; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.Size; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识库文档标签新增/修改 Request VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeDocumentLabelSaveReqVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "文档标签编号", example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "标签名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品") | ||
| 16 | + @NotBlank(message = "标签名称不能为空") | ||
| 17 | + @Size(max = 255, message = "标签名称不能超过 255 个字符") | ||
| 18 | + private String name; | ||
| 19 | + | ||
| 20 | + @Schema(description = "标签颜色", requiredMode = Schema.RequiredMode.REQUIRED, example = "#409EFF") | ||
| 21 | + @NotBlank(message = "标签颜色不能为空") | ||
| 22 | + @Size(max = 20, message = "标签颜色不能超过 20 个字符") | ||
| 23 | + private String color; | ||
| 24 | + | ||
| 25 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/permission/PmsKnowledgeContentPermissionRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.permission; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.util.List; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识内容协作权限 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeContentPermissionRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "协作权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 16 | + private Long libraryId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 19 | + private Boolean openStatus; | ||
| 20 | + | ||
| 21 | + @Schema(description = "公开协作等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 22 | + private Integer openLevel; | ||
| 23 | + | ||
| 24 | + @Schema(description = "创建人用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 25 | + private Long creatorUserId; | ||
| 26 | + | ||
| 27 | + @Schema(description = "当前用户协作等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 28 | + private Integer currentUserLevel; | ||
| 29 | + | ||
| 30 | + @Schema(description = "协作者列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 31 | + private List<Member> members; | ||
| 32 | + | ||
| 33 | + @Schema(description = "管理后台 - PMS 知识内容协作者 Response VO") | ||
| 34 | + @Data | ||
| 35 | + public static class Member { | ||
| 36 | + | ||
| 37 | + @Schema(description = "协作者编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 38 | + private Long id; | ||
| 39 | + | ||
| 40 | + @Schema(description = "用户编号", example = "1") | ||
| 41 | + private Long userId; | ||
| 42 | + | ||
| 43 | + @Schema(description = "用户昵称", example = "芋道") | ||
| 44 | + private String userName; | ||
| 45 | + | ||
| 46 | + @Schema(description = "部门编号", example = "100") | ||
| 47 | + private Long deptId; | ||
| 48 | + | ||
| 49 | + @Schema(description = "部门名称", example = "研发部") | ||
| 50 | + private String deptName; | ||
| 51 | + | ||
| 52 | + @Schema(description = "协作等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 53 | + private Integer level; | ||
| 54 | + | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/content/vo/permission/PmsKnowledgeContentPermissionUpdateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.content.vo.permission; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 4 | +import cn.iocoder.yudao.module.pms.enums.kb.content.PmsKnowledgeContentLevelEnum; | ||
| 5 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 7 | +import jakarta.validation.Valid; | ||
| 8 | +import jakarta.validation.constraints.AssertTrue; | ||
| 9 | +import jakarta.validation.constraints.NotNull; | ||
| 10 | +import lombok.Data; | ||
| 11 | + | ||
| 12 | +import java.util.List; | ||
| 13 | + | ||
| 14 | +@Schema(description = "管理后台 - PMS 更新知识内容协作权限 Request VO") | ||
| 15 | +@Data | ||
| 16 | +public class PmsKnowledgeContentPermissionUpdateReqVO { | ||
| 17 | + | ||
| 18 | + @Schema(description = "协作权限编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 19 | + @NotNull(message = "协作权限编号不能为空") | ||
| 20 | + private Long id; | ||
| 21 | + | ||
| 22 | + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 23 | + @NotNull(message = "是否公开不能为空") | ||
| 24 | + private Boolean openStatus; | ||
| 25 | + | ||
| 26 | + @Schema(description = "公开协作等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 27 | + @NotNull(message = "公开协作等级不能为空") | ||
| 28 | + @InEnum(PmsKnowledgeContentLevelEnum.class) | ||
| 29 | + private Integer openLevel; | ||
| 30 | + | ||
| 31 | + @Schema(description = "协作者列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 32 | + @Valid | ||
| 33 | + @NotNull(message = "协作者列表不能为空") | ||
| 34 | + private List<Member> members; | ||
| 35 | + | ||
| 36 | + @Schema(description = "管理后台 - PMS 知识内容协作者保存项") | ||
| 37 | + @Data | ||
| 38 | + public static class Member { | ||
| 39 | + | ||
| 40 | + @Schema(description = "用户编号", example = "1") | ||
| 41 | + private Long userId; | ||
| 42 | + | ||
| 43 | + @Schema(description = "部门编号", example = "100") | ||
| 44 | + private Long deptId; | ||
| 45 | + | ||
| 46 | + @Schema(description = "协作等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 47 | + @NotNull(message = "协作等级不能为空") | ||
| 48 | + @InEnum(PmsKnowledgeContentLevelEnum.class) | ||
| 49 | + private Integer level; | ||
| 50 | + | ||
| 51 | + @AssertTrue(message = "协作者必须且只能选择用户或部门") | ||
| 52 | + @JsonIgnore | ||
| 53 | + public boolean isUserOrDeptValid() { | ||
| 54 | + return (userId != null && deptId == null) || (userId == null && deptId != null); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/PmsKnowledgeDocumentCommentController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.comment.PmsKnowledgeDocumentCommentRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.comment.PmsKnowledgeDocumentCommentSaveReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.interaction.PmsKnowledgeDocumentCommentDO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeDocumentCommentService; | ||
| 10 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 11 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 12 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 13 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 14 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 15 | +import jakarta.annotation.Resource; | ||
| 16 | +import jakarta.validation.Valid; | ||
| 17 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 18 | +import org.springframework.validation.annotation.Validated; | ||
| 19 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 23 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 25 | +import org.springframework.web.bind.annotation.RestController; | ||
| 26 | + | ||
| 27 | +import java.util.ArrayList; | ||
| 28 | +import java.util.Collections; | ||
| 29 | +import java.util.List; | ||
| 30 | +import java.util.Map; | ||
| 31 | +import java.util.stream.Stream; | ||
| 32 | + | ||
| 33 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 35 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; | ||
| 36 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 37 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 38 | + | ||
| 39 | +@Tag(name = "管理后台 - PMS 知识库文档评论") | ||
| 40 | +@RestController | ||
| 41 | +@RequestMapping("/pms/kb/document-comment") | ||
| 42 | +@Validated | ||
| 43 | +public class PmsKnowledgeDocumentCommentController { | ||
| 44 | + | ||
| 45 | + @Resource | ||
| 46 | + private PmsKnowledgeDocumentCommentService commentService; | ||
| 47 | + | ||
| 48 | + @Resource | ||
| 49 | + private AdminUserApi adminUserApi; | ||
| 50 | + | ||
| 51 | + @PostMapping("/create") | ||
| 52 | + @Operation(summary = "创建知识库文档评论") | ||
| 53 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 54 | + public CommonResult<Long> createDocumentComment(@Valid @RequestBody PmsKnowledgeDocumentCommentSaveReqVO saveReqVO) { | ||
| 55 | + return success(commentService.createDocumentComment(saveReqVO, getLoginUserId())); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + @DeleteMapping("/delete") | ||
| 59 | + @Operation(summary = "删除知识库文档评论") | ||
| 60 | + @Parameter(name = "id", description = "评论编号", required = true, example = "1024") | ||
| 61 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 62 | + public CommonResult<Boolean> deleteDocumentComment(@RequestParam("id") Long id) { | ||
| 63 | + commentService.deleteDocumentComment(id, getLoginUserId()); | ||
| 64 | + return success(true); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + @GetMapping("/list") | ||
| 68 | + @Operation(summary = "获得知识库文档评论列表") | ||
| 69 | + @Parameter(name = "documentId", description = "文档编号", required = true, example = "1024") | ||
| 70 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 71 | + public CommonResult<List<PmsKnowledgeDocumentCommentRespVO>> getDocumentCommentList( | ||
| 72 | + @RequestParam("documentId") Long documentId) { | ||
| 73 | + List<PmsKnowledgeDocumentCommentDO> comments = commentService.getDocumentCommentList(documentId, getLoginUserId()); | ||
| 74 | + return success(buildCommentRespVOList(comments)); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + // ==================== 拼接 VO ==================== | ||
| 78 | + | ||
| 79 | + private List<PmsKnowledgeDocumentCommentRespVO> buildCommentRespVOList( | ||
| 80 | + List<PmsKnowledgeDocumentCommentDO> comments) { | ||
| 81 | + if (CollUtil.isEmpty(comments)) { | ||
| 82 | + return Collections.emptyList(); | ||
| 83 | + } | ||
| 84 | + // 1. 批量查询评论人和回复对象 | ||
| 85 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(comments, | ||
| 86 | + comment -> Stream.of(comment.getUserId(), comment.getReplyUserId()))); | ||
| 87 | + | ||
| 88 | + // 2. 批量转换评论,避免回复组装依赖查询顺序 | ||
| 89 | + Map<Long, PmsKnowledgeDocumentCommentRespVO> commentMap = convertMap(comments, | ||
| 90 | + PmsKnowledgeDocumentCommentDO::getId, comment -> { | ||
| 91 | + PmsKnowledgeDocumentCommentRespVO commentVO = BeanUtils.toBean(comment, | ||
| 92 | + PmsKnowledgeDocumentCommentRespVO.class).setChildren(new ArrayList<>()); | ||
| 93 | + findAndThen(userMap, comment.getUserId(), user -> commentVO.setUserName(user.getNickname())); | ||
| 94 | + findAndThen(userMap, comment.getReplyUserId(), | ||
| 95 | + user -> commentVO.setReplyUserName(user.getNickname())); | ||
| 96 | + return commentVO; | ||
| 97 | + }); | ||
| 98 | + | ||
| 99 | + // 3. 按主评论组织回复列表 | ||
| 100 | + List<PmsKnowledgeDocumentCommentRespVO> result = new ArrayList<>(); | ||
| 101 | + for (PmsKnowledgeDocumentCommentDO comment : comments) { | ||
| 102 | + PmsKnowledgeDocumentCommentRespVO commentVO = commentMap.get(comment.getId()); | ||
| 103 | + if (PmsKnowledgeDocumentCommentDO.MAIN_ID_ROOT.equals(comment.getMainId())) { | ||
| 104 | + result.add(commentVO); | ||
| 105 | + continue; | ||
| 106 | + } | ||
| 107 | + findAndThen(commentMap, comment.getMainId(), mainComment -> mainComment.getChildren().add(commentVO)); | ||
| 108 | + } | ||
| 109 | + return result; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/PmsKnowledgeDocumentLikeController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeDocumentLikeService; | ||
| 5 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 6 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 7 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 8 | +import jakarta.annotation.Resource; | ||
| 9 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 10 | +import org.springframework.validation.annotation.Validated; | ||
| 11 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 12 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 13 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 14 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 15 | +import org.springframework.web.bind.annotation.RestController; | ||
| 16 | + | ||
| 17 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 18 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 19 | + | ||
| 20 | +@Tag(name = "管理后台 - PMS 知识库文档点赞") | ||
| 21 | +@RestController | ||
| 22 | +@RequestMapping("/pms/kb/document-like") | ||
| 23 | +@Validated | ||
| 24 | +public class PmsKnowledgeDocumentLikeController { | ||
| 25 | + | ||
| 26 | + @Resource | ||
| 27 | + private PmsKnowledgeDocumentLikeService documentLikeService; | ||
| 28 | + | ||
| 29 | + @PostMapping("/create") | ||
| 30 | + @Operation(summary = "点赞文档") | ||
| 31 | + @Parameter(name = "documentId", description = "文档编号", required = true, example = "1024") | ||
| 32 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 33 | + public CommonResult<Boolean> createDocumentLike(@RequestParam("documentId") Long documentId) { | ||
| 34 | + documentLikeService.createDocumentLike(documentId, getLoginUserId()); | ||
| 35 | + return success(true); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @DeleteMapping("/delete") | ||
| 39 | + @Operation(summary = "取消点赞文档") | ||
| 40 | + @Parameter(name = "documentId", description = "文档编号", required = true, example = "1024") | ||
| 41 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 42 | + public CommonResult<Boolean> deleteDocumentLike(@RequestParam("documentId") Long documentId) { | ||
| 43 | + documentLikeService.deleteDocumentLike(documentId, getLoginUserId()); | ||
| 44 | + return success(true); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/PmsKnowledgeDocumentShareController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | ||
| 6 | +import cn.iocoder.yudao.module.infra.api.file.FileApi; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.share.PmsKnowledgeDocumentSharePublicRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.share.PmsKnowledgeDocumentShareRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.share.PmsKnowledgeDocumentShareSaveReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.share.PmsKnowledgeDocumentShareUpdateMemberListReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.content.PmsKnowledgeDocumentDO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.interaction.PmsKnowledgeDocumentShareDO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.enums.kb.content.PmsKnowledgeDocumentTypeEnum; | ||
| 14 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeDocumentShareService; | ||
| 15 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 16 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 17 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 18 | +import jakarta.annotation.Resource; | ||
| 19 | +import jakarta.annotation.security.PermitAll; | ||
| 20 | +import jakarta.validation.Valid; | ||
| 21 | +import jakarta.validation.constraints.NotBlank; | ||
| 22 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 23 | +import org.springframework.validation.annotation.Validated; | ||
| 24 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 25 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 27 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 28 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 29 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 30 | +import org.springframework.web.bind.annotation.RestController; | ||
| 31 | + | ||
| 32 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 33 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 34 | + | ||
| 35 | +@Tag(name = "管理后台 - PMS 知识库文档分享") | ||
| 36 | +@RestController | ||
| 37 | +@RequestMapping("/pms/kb/document-share") | ||
| 38 | +@Validated | ||
| 39 | +public class PmsKnowledgeDocumentShareController { | ||
| 40 | + | ||
| 41 | + @Resource | ||
| 42 | + private PmsKnowledgeDocumentShareService documentShareService; | ||
| 43 | + | ||
| 44 | + @Resource | ||
| 45 | + private FileApi fileApi; | ||
| 46 | + | ||
| 47 | + @PostMapping("/open") | ||
| 48 | + @Operation(summary = "开启文档分享") | ||
| 49 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 50 | + public CommonResult<PmsKnowledgeDocumentShareRespVO> openShare( | ||
| 51 | + @Valid @RequestBody PmsKnowledgeDocumentShareSaveReqVO reqVO) { | ||
| 52 | + PmsKnowledgeDocumentShareDO share = documentShareService.openShare(reqVO.getDocumentId(), | ||
| 53 | + reqVO.getShareUserIds(), getLoginUserId()); | ||
| 54 | + return success(BeanUtils.toBean(share, PmsKnowledgeDocumentShareRespVO.class)); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @PutMapping("/update-member-list") | ||
| 58 | + @Operation(summary = "更新文档内部分享成员") | ||
| 59 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 60 | + public CommonResult<Boolean> updateShareMemberList( | ||
| 61 | + @Valid @RequestBody PmsKnowledgeDocumentShareUpdateMemberListReqVO reqVO) { | ||
| 62 | + documentShareService.updateShareMemberList(reqVO.getDocumentId(), reqVO.getShareUserIds(), getLoginUserId()); | ||
| 63 | + return success(true); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + @PutMapping("/close") | ||
| 67 | + @Operation(summary = "关闭文档分享") | ||
| 68 | + @Parameter(name = "documentId", description = "文档编号", required = true, example = "1024") | ||
| 69 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 70 | + public CommonResult<Boolean> closeShare(@RequestParam("documentId") Long documentId) { | ||
| 71 | + documentShareService.closeShare(documentId, getLoginUserId()); | ||
| 72 | + return success(true); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + @GetMapping("/get") | ||
| 76 | + @Operation(summary = "获得文档分享配置") | ||
| 77 | + @Parameter(name = "documentId", description = "文档编号", required = true, example = "1024") | ||
| 78 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 79 | + public CommonResult<PmsKnowledgeDocumentShareRespVO> getDocumentShare(@RequestParam("documentId") Long documentId) { | ||
| 80 | + PmsKnowledgeDocumentShareDO share = documentShareService.getActiveDocumentShare(documentId, getLoginUserId()); | ||
| 81 | + return success(BeanUtils.toBean(share, PmsKnowledgeDocumentShareRespVO.class)); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + @GetMapping("/get-by-token") | ||
| 85 | + @Operation(summary = "通过分享令牌获得文档") | ||
| 86 | + @Parameter(name = "token", description = "分享令牌", required = true) | ||
| 87 | + @PermitAll | ||
| 88 | + @TenantIgnore | ||
| 89 | + public CommonResult<PmsKnowledgeDocumentSharePublicRespVO> getDocumentByToken( | ||
| 90 | + @RequestParam("token") @NotBlank(message = "分享令牌不能为空") String token) { | ||
| 91 | + PmsKnowledgeDocumentDO document = documentShareService.getDocumentByShareToken(token); | ||
| 92 | + PmsKnowledgeDocumentSharePublicRespVO documentVO = BeanUtils.toBean( | ||
| 93 | + document, PmsKnowledgeDocumentSharePublicRespVO.class); | ||
| 94 | + if (PmsKnowledgeDocumentTypeEnum.FILE.getType().equals(document.getType())) { | ||
| 95 | + documentVO.setContent(null).setPreviewUrl( | ||
| 96 | + fileApi.presignGetUrl(document.getContent(), null)); | ||
| 97 | + } | ||
| 98 | + return success(documentVO); | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/PmsKnowledgeFavoriteController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.PmsKnowledgeInteractionItemRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.favorite.PmsKnowledgeFavoritePageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.favorite.PmsKnowledgeFavoriteSaveReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.enums.kb.PmsKnowledgeObjectTypeEnum; | ||
| 10 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeFavoriteService; | ||
| 11 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 12 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 13 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 14 | +import jakarta.annotation.Resource; | ||
| 15 | +import jakarta.validation.Valid; | ||
| 16 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 17 | +import org.springframework.validation.annotation.Validated; | ||
| 18 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 22 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 23 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 24 | +import org.springframework.web.bind.annotation.RestController; | ||
| 25 | + | ||
| 26 | +import java.util.List; | ||
| 27 | + | ||
| 28 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 29 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 30 | + | ||
| 31 | +@Tag(name = "管理后台 - PMS 知识关注") | ||
| 32 | +@RestController | ||
| 33 | +@RequestMapping("/pms/kb/favorite") | ||
| 34 | +@Validated | ||
| 35 | +public class PmsKnowledgeFavoriteController { | ||
| 36 | + | ||
| 37 | + @Resource | ||
| 38 | + private PmsKnowledgeFavoriteService favoriteService; | ||
| 39 | + | ||
| 40 | + @PostMapping("/create") | ||
| 41 | + @Operation(summary = "关注知识对象") | ||
| 42 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 43 | + public CommonResult<Boolean> createFavorite(@Valid @RequestBody PmsKnowledgeFavoriteSaveReqVO saveReqVO) { | ||
| 44 | + favoriteService.createFavorite(saveReqVO, getLoginUserId()); | ||
| 45 | + return success(true); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @DeleteMapping("/delete") | ||
| 49 | + @Operation(summary = "取消关注知识对象") | ||
| 50 | + @Parameter(name = "type", description = "对象类型", required = true, example = "3") | ||
| 51 | + @Parameter(name = "entityId", description = "对象编号", required = true, example = "1024") | ||
| 52 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 53 | + public CommonResult<Boolean> deleteFavorite( | ||
| 54 | + @RequestParam("type") @InEnum(PmsKnowledgeObjectTypeEnum.class) Integer type, | ||
| 55 | + @RequestParam("entityId") Long entityId) { | ||
| 56 | + favoriteService.deleteFavorite(type, entityId, getLoginUserId()); | ||
| 57 | + return success(true); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + @GetMapping("/page") | ||
| 61 | + @Operation(summary = "获得我的关注分页") | ||
| 62 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 63 | + public CommonResult<PageResult<PmsKnowledgeInteractionItemRespVO>> getFavoritePage( | ||
| 64 | + @Valid PmsKnowledgeFavoritePageReqVO pageReqVO) { | ||
| 65 | + return success(favoriteService.getFavoritePage(pageReqVO, getLoginUserId())); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + @GetMapping("/list") | ||
| 69 | + @Operation(summary = "获得知识库内我的关注列表") | ||
| 70 | + @Parameter(name = "libraryId", description = "知识库编号", required = true, example = "1024") | ||
| 71 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 72 | + public CommonResult<List<PmsKnowledgeInteractionItemRespVO>> getFavoriteListByLibraryId( | ||
| 73 | + @RequestParam("libraryId") Long libraryId) { | ||
| 74 | + return success(favoriteService.getFavoriteListByLibraryId(libraryId, getLoginUserId())); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/PmsKnowledgeViewRecordController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.viewrecord.PmsKnowledgeRecentListRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeViewRecordService; | ||
| 6 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 7 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 8 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 9 | +import jakarta.annotation.Resource; | ||
| 10 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 11 | +import org.springframework.validation.annotation.Validated; | ||
| 12 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 13 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 14 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 15 | +import org.springframework.web.bind.annotation.RestController; | ||
| 16 | + | ||
| 17 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 18 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 19 | + | ||
| 20 | +@Tag(name = "管理后台 - PMS 知识最近浏览") | ||
| 21 | +@RestController | ||
| 22 | +@RequestMapping("/pms/kb/view-record") | ||
| 23 | +@Validated | ||
| 24 | +public class PmsKnowledgeViewRecordController { | ||
| 25 | + | ||
| 26 | + @Resource | ||
| 27 | + private PmsKnowledgeViewRecordService viewRecordService; | ||
| 28 | + | ||
| 29 | + @GetMapping("/recent-list") | ||
| 30 | + @Operation(summary = "获得最近浏览列表") | ||
| 31 | + @Parameter(name = "libraryId", description = "知识库编号;不传时查询全部可读知识库", example = "1024") | ||
| 32 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 33 | + public CommonResult<PmsKnowledgeRecentListRespVO> getRecentViewRecordList( | ||
| 34 | + @RequestParam(value = "libraryId", required = false) Long libraryId) { | ||
| 35 | + return success(viewRecordService.getRecentViewRecordList(libraryId, getLoginUserId())); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/PmsKnowledgeInteractionItemRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识交互对象 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeInteractionItemRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "对象类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 16 | + private Integer type; | ||
| 17 | + | ||
| 18 | + @Schema(description = "对象编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 19 | + private Long entityId; | ||
| 20 | + | ||
| 21 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 22 | + private Long libraryId; | ||
| 23 | + | ||
| 24 | + @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品知识库") | ||
| 25 | + private String libraryName; | ||
| 26 | + | ||
| 27 | + @Schema(description = "对象名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品说明") | ||
| 28 | + private String name; | ||
| 29 | + | ||
| 30 | + @Schema(description = "知识库简介") | ||
| 31 | + private String description; | ||
| 32 | + | ||
| 33 | + @Schema(description = "文件夹编号", example = "1024") | ||
| 34 | + private Long folderId; | ||
| 35 | + | ||
| 36 | + @Schema(description = "文档编号", example = "1024") | ||
| 37 | + private Long documentId; | ||
| 38 | + | ||
| 39 | + @Schema(description = "文件类型", example = "pdf") | ||
| 40 | + private String fileType; | ||
| 41 | + | ||
| 42 | + @Schema(description = "文件大小,单位:字节") | ||
| 43 | + private Long fileSize; | ||
| 44 | + | ||
| 45 | + @Schema(description = "对象更新时间") | ||
| 46 | + private LocalDateTime targetUpdateTime; | ||
| 47 | + | ||
| 48 | + @Schema(description = "记录时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 49 | + private LocalDateTime createTime; | ||
| 50 | + | ||
| 51 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/comment/PmsKnowledgeDocumentCommentRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.comment; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库文档评论 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeDocumentCommentRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "评论编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + private Long documentId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "评论人用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 20 | + private Long userId; | ||
| 21 | + | ||
| 22 | + @Schema(description = "评论人昵称", example = "芋道") | ||
| 23 | + private String userName; | ||
| 24 | + | ||
| 25 | + @Schema(description = "主评论编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||
| 26 | + private Long mainId; | ||
| 27 | + | ||
| 28 | + @Schema(description = "回复对象用户编号", example = "2") | ||
| 29 | + private Long replyUserId; | ||
| 30 | + | ||
| 31 | + @Schema(description = "回复对象昵称", example = "源码") | ||
| 32 | + private String replyUserName; | ||
| 33 | + | ||
| 34 | + @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 35 | + private String content; | ||
| 36 | + | ||
| 37 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 38 | + private LocalDateTime createTime; | ||
| 39 | + | ||
| 40 | + @Schema(description = "回复列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 41 | + private List<PmsKnowledgeDocumentCommentRespVO> children; | ||
| 42 | + | ||
| 43 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/comment/PmsKnowledgeDocumentCommentSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.comment; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 6 | +import jakarta.validation.constraints.Size; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库文档评论保存 Request VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeDocumentCommentSaveReqVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + @NotNull(message = "文档编号不能为空") | ||
| 15 | + private Long documentId; | ||
| 16 | + | ||
| 17 | + @Schema(description = "主评论编号", example = "0") | ||
| 18 | + private Long mainId; | ||
| 19 | + | ||
| 20 | + @Schema(description = "回复对象用户编号", example = "1") | ||
| 21 | + private Long replyUserId; | ||
| 22 | + | ||
| 23 | + @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "文档内容很清楚") | ||
| 24 | + @NotBlank(message = "评论内容不能为空") | ||
| 25 | + @Size(max = 2000, message = "评论内容不能超过 2000 个字符") | ||
| 26 | + private String content; | ||
| 27 | + | ||
| 28 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/favorite/PmsKnowledgeFavoritePageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.favorite; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import cn.iocoder.yudao.module.pms.enums.kb.PmsKnowledgeObjectTypeEnum; | ||
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - PMS 知识收藏(关注)分页 Request VO") | ||
| 11 | +@Data | ||
| 12 | +@EqualsAndHashCode(callSuper = true) | ||
| 13 | +public class PmsKnowledgeFavoritePageReqVO extends PageParam { | ||
| 14 | + | ||
| 15 | + @Schema(description = "对象类型", example = "3") | ||
| 16 | + @InEnum(value = PmsKnowledgeObjectTypeEnum.class, message = "对象类型必须是 {value}") | ||
| 17 | + private Integer type; | ||
| 18 | + | ||
| 19 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/favorite/PmsKnowledgeFavoriteSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.favorite; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 4 | +import cn.iocoder.yudao.module.pms.enums.kb.PmsKnowledgeObjectTypeEnum; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import jakarta.validation.constraints.NotNull; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识收藏(关注)保存 Request VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeFavoriteSaveReqVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "对象类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 14 | + @NotNull(message = "对象类型不能为空") | ||
| 15 | + @InEnum(value = PmsKnowledgeObjectTypeEnum.class, message = "对象类型必须是 {value}") | ||
| 16 | + private Integer type; | ||
| 17 | + | ||
| 18 | + @Schema(description = "对象编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 19 | + @NotNull(message = "对象编号不能为空") | ||
| 20 | + private Long entityId; | ||
| 21 | + | ||
| 22 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/share/PmsKnowledgeDocumentSharePublicRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.share; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "PMS 知识库文档公开分享 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeDocumentSharePublicRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "文档标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品说明") | ||
| 16 | + private String title; | ||
| 17 | + | ||
| 18 | + @Schema(description = "文档内容或文件地址") | ||
| 19 | + private String content; | ||
| 20 | + | ||
| 21 | + @Schema(description = "文件临时预览地址") | ||
| 22 | + private String previewUrl; | ||
| 23 | + | ||
| 24 | + @Schema(description = "文档类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 25 | + private Integer type; | ||
| 26 | + | ||
| 27 | + @Schema(description = "文件类型", example = "pdf") | ||
| 28 | + private String fileType; | ||
| 29 | + | ||
| 30 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 31 | + private LocalDateTime updateTime; | ||
| 32 | + | ||
| 33 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/share/PmsKnowledgeDocumentShareRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.share; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库文档分享 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeDocumentShareRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "分享编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + private Long documentId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "内部分享成员用户编号列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 20 | + private List<Long> shareUserIds; | ||
| 21 | + | ||
| 22 | + @Schema(description = "外部查看令牌", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 23 | + private String token; | ||
| 24 | + | ||
| 25 | + @Schema(description = "分享状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 26 | + private Integer status; | ||
| 27 | + | ||
| 28 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 29 | + private LocalDateTime createTime; | ||
| 30 | + | ||
| 31 | + @Schema(description = "关闭人用户编号") | ||
| 32 | + private Long closeUserId; | ||
| 33 | + | ||
| 34 | + @Schema(description = "关闭时间") | ||
| 35 | + private LocalDateTime closeTime; | ||
| 36 | + | ||
| 37 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/share/PmsKnowledgeDocumentShareSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.share; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库文档分享保存 Request VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeDocumentShareSaveReqVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + @NotNull(message = "文档编号不能为空") | ||
| 15 | + private Long documentId; | ||
| 16 | + | ||
| 17 | + @Schema(description = "内部分享成员用户编号列表") | ||
| 18 | + private List<@NotNull(message = "分享成员用户编号不能为空") Long> shareUserIds; | ||
| 19 | + | ||
| 20 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/share/PmsKnowledgeDocumentShareUpdateMemberListReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.share; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库文档分享成员列表更新 Request VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeDocumentShareUpdateMemberListReqVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + @NotNull(message = "文档编号不能为空") | ||
| 15 | + private Long documentId; | ||
| 16 | + | ||
| 17 | + @Schema(description = "内部分享成员用户编号列表") | ||
| 18 | + private List<@NotNull(message = "分享成员用户编号不能为空") Long> shareUserIds; | ||
| 19 | + | ||
| 20 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/interaction/vo/viewrecord/PmsKnowledgeRecentListRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.viewrecord; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.interaction.vo.PmsKnowledgeInteractionItemRespVO; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识最近浏览 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeRecentListRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "今天浏览列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 14 | + private List<PmsKnowledgeInteractionItemRespVO> todayItems; | ||
| 15 | + | ||
| 16 | + @Schema(description = "昨天浏览列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 17 | + private List<PmsKnowledgeInteractionItemRespVO> yesterdayItems; | ||
| 18 | + | ||
| 19 | + @Schema(description = "更早 30 天浏览列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 20 | + private List<PmsKnowledgeInteractionItemRespVO> recent30DayItems; | ||
| 21 | + | ||
| 22 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/PmsKnowledgeGroupController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.group.PmsKnowledgeGroupRespVO; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.group.PmsKnowledgeGroupSaveReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.group.PmsKnowledgeGroupSortReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.group.PmsKnowledgeLibraryMoveGroupReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.library.PmsKnowledgeGroupDO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.service.kb.library.PmsKnowledgeGroupService; | ||
| 11 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 12 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 13 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 14 | +import jakarta.annotation.Resource; | ||
| 15 | +import jakarta.validation.Valid; | ||
| 16 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 17 | +import org.springframework.validation.annotation.Validated; | ||
| 18 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 23 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 25 | +import org.springframework.web.bind.annotation.RestController; | ||
| 26 | + | ||
| 27 | +import java.util.List; | ||
| 28 | +import java.util.Map; | ||
| 29 | + | ||
| 30 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 31 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 32 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 33 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 34 | + | ||
| 35 | +@Tag(name = "管理后台 - PMS 知识库分组") | ||
| 36 | +@RestController | ||
| 37 | +@RequestMapping("/pms/kb/group") | ||
| 38 | +@Validated | ||
| 39 | +public class PmsKnowledgeGroupController { | ||
| 40 | + | ||
| 41 | + @Resource | ||
| 42 | + private PmsKnowledgeGroupService knowledgeGroupService; | ||
| 43 | + | ||
| 44 | + @PostMapping("/create") | ||
| 45 | + @Operation(summary = "创建知识库分组") | ||
| 46 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:create')") | ||
| 47 | + public CommonResult<Long> createGroup(@Valid @RequestBody PmsKnowledgeGroupSaveReqVO saveReqVO) { | ||
| 48 | + return success(knowledgeGroupService.createGroup(saveReqVO, getLoginUserId())); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + @PutMapping("/update") | ||
| 52 | + @Operation(summary = "修改知识库分组") | ||
| 53 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 54 | + public CommonResult<Boolean> updateGroup(@Valid @RequestBody PmsKnowledgeGroupSaveReqVO saveReqVO) { | ||
| 55 | + knowledgeGroupService.updateGroup(saveReqVO, getLoginUserId()); | ||
| 56 | + return success(true); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + @PutMapping("/update-sort") | ||
| 60 | + @Operation(summary = "修改知识库分组排序") | ||
| 61 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 62 | + public CommonResult<Boolean> updateGroupSort( | ||
| 63 | + @Valid @RequestBody PmsKnowledgeGroupSortReqVO sortReqVO) { | ||
| 64 | + knowledgeGroupService.updateGroupSort(sortReqVO, getLoginUserId()); | ||
| 65 | + return success(true); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + @DeleteMapping("/delete") | ||
| 69 | + @Operation(summary = "删除知识库分组") | ||
| 70 | + @Parameter(name = "id", description = "知识库分组编号", required = true, example = "1024") | ||
| 71 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 72 | + public CommonResult<Boolean> deleteGroup(@RequestParam("id") Long id) { | ||
| 73 | + knowledgeGroupService.deleteGroup(id, getLoginUserId()); | ||
| 74 | + return success(true); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @GetMapping("/list") | ||
| 78 | + @Operation(summary = "获得知识库分组列表") | ||
| 79 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 80 | + public CommonResult<List<PmsKnowledgeGroupRespVO>> getGroupList() { | ||
| 81 | + Long userId = getLoginUserId(); | ||
| 82 | + List<PmsKnowledgeGroupDO> groups = knowledgeGroupService.getGroupList(userId); | ||
| 83 | + Map<Long, Integer> groupCountMap = knowledgeGroupService.getGroupLibraryCountMap(userId, | ||
| 84 | + convertSet(groups, PmsKnowledgeGroupDO::getId)); | ||
| 85 | + return success(convertList(groups, group -> BeanUtils.toBean(group, PmsKnowledgeGroupRespVO.class) | ||
| 86 | + .setLibraryCount(groupCountMap.getOrDefault(group.getId(), 0)))); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + @GetMapping("/get") | ||
| 90 | + @Operation(summary = "获得知识库分组") | ||
| 91 | + @Parameter(name = "id", description = "知识库分组编号", required = true, example = "1024") | ||
| 92 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 93 | + public CommonResult<PmsKnowledgeGroupRespVO> getGroup(@RequestParam("id") Long id) { | ||
| 94 | + return success(BeanUtils.toBean(knowledgeGroupService.getGroup(id, getLoginUserId()), | ||
| 95 | + PmsKnowledgeGroupRespVO.class)); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + @PutMapping("/move") | ||
| 99 | + @Operation(summary = "移动知识库到个人分组") | ||
| 100 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 101 | + public CommonResult<Boolean> moveLibraryToGroup( | ||
| 102 | + @Valid @RequestBody PmsKnowledgeLibraryMoveGroupReqVO moveReqVO) { | ||
| 103 | + knowledgeGroupService.moveLibraryToGroup(moveReqVO, getLoginUserId()); | ||
| 104 | + return success(true); | ||
| 105 | + } | ||
| 106 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/PmsKnowledgeLibraryController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 7 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.library.PmsKnowledgeLibraryPageReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.library.PmsKnowledgeLibraryRespVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.library.PmsKnowledgeLibrarySaveReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.library.PmsKnowledgeLibraryDO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.library.PmsKnowledgeLibraryMemberDO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.enums.kb.PmsKnowledgeObjectTypeEnum; | ||
| 14 | +import cn.iocoder.yudao.module.pms.enums.kb.content.PmsKnowledgeDocumentTypeEnum; | ||
| 15 | +import cn.iocoder.yudao.module.pms.enums.kb.library.PmsKnowledgeLibraryMemberLevelEnum; | ||
| 16 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeDocumentService; | ||
| 17 | +import cn.iocoder.yudao.module.pms.service.kb.interaction.PmsKnowledgeFavoriteService; | ||
| 18 | +import cn.iocoder.yudao.module.pms.service.kb.library.PmsKnowledgeLibraryMemberService; | ||
| 19 | +import cn.iocoder.yudao.module.pms.service.kb.library.PmsKnowledgeLibraryService; | ||
| 20 | +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | ||
| 21 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 22 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 23 | +import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; | ||
| 24 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 25 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 26 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 27 | +import jakarta.annotation.Resource; | ||
| 28 | +import jakarta.validation.Valid; | ||
| 29 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 30 | +import org.springframework.validation.annotation.Validated; | ||
| 31 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 32 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 33 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 34 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 35 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 36 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 37 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 38 | +import org.springframework.web.bind.annotation.RestController; | ||
| 39 | + | ||
| 40 | +import java.util.Collections; | ||
| 41 | +import java.util.List; | ||
| 42 | +import java.util.Map; | ||
| 43 | +import java.util.Set; | ||
| 44 | + | ||
| 45 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 46 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 47 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 48 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 49 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 50 | + | ||
| 51 | +@Tag(name = "管理后台 - PMS 知识库") | ||
| 52 | +@RestController | ||
| 53 | +@RequestMapping("/pms/kb/library") | ||
| 54 | +@Validated | ||
| 55 | +public class PmsKnowledgeLibraryController { | ||
| 56 | + | ||
| 57 | + @Resource | ||
| 58 | + private PmsKnowledgeLibraryService libraryService; | ||
| 59 | + @Resource | ||
| 60 | + private PmsKnowledgeLibraryMemberService memberService; | ||
| 61 | + @Resource | ||
| 62 | + private PmsKnowledgeDocumentService documentService; | ||
| 63 | + @Resource | ||
| 64 | + private PmsKnowledgeFavoriteService favoriteService; | ||
| 65 | + | ||
| 66 | + @Resource | ||
| 67 | + private AdminUserApi adminUserApi; | ||
| 68 | + @Resource | ||
| 69 | + private PermissionApi permissionApi; | ||
| 70 | + | ||
| 71 | + @PostMapping("/create") | ||
| 72 | + @Operation(summary = "创建知识库") | ||
| 73 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:create')") | ||
| 74 | + public CommonResult<Long> createLibrary(@Valid @RequestBody PmsKnowledgeLibrarySaveReqVO saveReqVO) { | ||
| 75 | + return success(libraryService.createLibrary(saveReqVO, getLoginUserId())); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + @PutMapping("/update") | ||
| 79 | + @Operation(summary = "更新知识库") | ||
| 80 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 81 | + public CommonResult<Boolean> updateLibrary(@Valid @RequestBody PmsKnowledgeLibrarySaveReqVO saveReqVO) { | ||
| 82 | + libraryService.updateLibrary(saveReqVO, getLoginUserId()); | ||
| 83 | + return success(true); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + @DeleteMapping("/delete") | ||
| 87 | + @Operation(summary = "删除知识库") | ||
| 88 | + @Parameter(name = "id", description = "知识库编号", required = true, example = "1024") | ||
| 89 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 90 | + public CommonResult<Boolean> deleteLibrary(@RequestParam("id") Long id) { | ||
| 91 | + libraryService.deleteLibrary(id, getLoginUserId()); | ||
| 92 | + return success(true); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + @GetMapping("/get") | ||
| 96 | + @Operation(summary = "获得知识库详情") | ||
| 97 | + @Parameter(name = "id", description = "知识库编号", required = true, example = "1024") | ||
| 98 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 99 | + public CommonResult<PmsKnowledgeLibraryRespVO> getLibrary(@RequestParam("id") Long id) { | ||
| 100 | + Long userId = getLoginUserId(); | ||
| 101 | + PmsKnowledgeLibraryDO library = memberService.validateLibraryReadable(id, userId); | ||
| 102 | + return success(CollUtil.getFirst(buildLibraryRespVOList(Collections.singletonList(library), userId))); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + @GetMapping("/page") | ||
| 106 | + @Operation(summary = "获得知识库分页") | ||
| 107 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 108 | + public CommonResult<PageResult<PmsKnowledgeLibraryRespVO>> getLibraryPage( | ||
| 109 | + @Valid PmsKnowledgeLibraryPageReqVO pageReqVO) { | ||
| 110 | + Long userId = getLoginUserId(); | ||
| 111 | + PageResult<PmsKnowledgeLibraryDO> pageResult = libraryService.getLibraryPage(pageReqVO, userId); | ||
| 112 | + return success(new PageResult<>(buildLibraryRespVOList(pageResult.getList(), userId), pageResult.getTotal())); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + // ==================== 拼接 VO ==================== | ||
| 116 | + | ||
| 117 | + private List<PmsKnowledgeLibraryRespVO> buildLibraryRespVOList( | ||
| 118 | + List<PmsKnowledgeLibraryDO> libraries, Long userId) { | ||
| 119 | + if (CollUtil.isEmpty(libraries)) { | ||
| 120 | + return Collections.emptyList(); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + // 1. 批量查询知识库成员、内容数量、创建人和当前用户权限信息 | ||
| 124 | + Set<Long> libraryIds = convertSet(libraries, PmsKnowledgeLibraryDO::getId); | ||
| 125 | + Map<Long, List<PmsKnowledgeLibraryMemberDO>> memberListMap = memberService.getLibraryMemberListMap(libraryIds); | ||
| 126 | + Map<Long, Map<Integer, Long>> documentTypeCountMap = documentService.getDocumentTypeCountMap(libraryIds); | ||
| 127 | + Set<Long> userIds = convertSet(libraries, library -> NumberUtils.parseLong(library.getCreator())); | ||
| 128 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||
| 129 | + AdminUserRespDTO currentUser = adminUserApi.getUser(userId); | ||
| 130 | + Long deptId = currentUser != null ? currentUser.getDeptId() : null; | ||
| 131 | + boolean superAdmin = permissionApi.hasAnyRoles(userId, RoleCodeEnum.SUPER_ADMIN.getCode()); | ||
| 132 | + Set<Long> favoriteLibraryIds = favoriteService.getFavoriteEntityIdSet( | ||
| 133 | + PmsKnowledgeObjectTypeEnum.LIBRARY.getType(), libraryIds, userId); | ||
| 134 | + | ||
| 135 | + // 2. 拼接每个知识库的成员权限、统计数量、收藏状态和创建人名称 | ||
| 136 | + return convertList(libraries, library -> { | ||
| 137 | + List<PmsKnowledgeLibraryMemberDO> members = memberListMap.getOrDefault(library.getId(), Collections.emptyList()); | ||
| 138 | + PmsKnowledgeLibraryMemberDO directMember = CollUtil.findOne(members, member -> userId.equals(member.getUserId())); | ||
| 139 | + PmsKnowledgeLibraryMemberDO currentMember = directMember; | ||
| 140 | + if (currentMember == null && deptId != null) { | ||
| 141 | + currentMember = CollUtil.findOne(members, member -> deptId.equals(member.getDeptId())); | ||
| 142 | + } | ||
| 143 | + boolean adminStatus = superAdmin || currentMember != null | ||
| 144 | + && (PmsKnowledgeLibraryMemberLevelEnum.CREATOR.getLevel().equals(currentMember.getLevel()) | ||
| 145 | + || PmsKnowledgeLibraryMemberLevelEnum.ADMIN.getLevel().equals(currentMember.getLevel())); | ||
| 146 | + PmsKnowledgeLibraryRespVO libraryVO = BeanUtils.toBean(library, PmsKnowledgeLibraryRespVO.class) | ||
| 147 | + .setCreatorUserId(NumberUtils.parseLong(library.getCreator())).setMemberCount(members.size()) | ||
| 148 | + .setWriteStatus(superAdmin || currentMember != null).setAdminStatus(adminStatus) | ||
| 149 | + .setExitStatus(directMember != null && !PmsKnowledgeLibraryMemberLevelEnum.CREATOR.getLevel().equals(directMember.getLevel())) | ||
| 150 | + .setFavoriteStatus(favoriteLibraryIds.contains(library.getId())); | ||
| 151 | + Map<Integer, Long> typeCountMap = documentTypeCountMap.getOrDefault(library.getId(), Collections.emptyMap()); | ||
| 152 | + libraryVO.setDocumentCount(typeCountMap.getOrDefault(PmsKnowledgeDocumentTypeEnum.RICH_TEXT.getType(), 0L)) | ||
| 153 | + .setFileCount(typeCountMap.getOrDefault(PmsKnowledgeDocumentTypeEnum.FILE.getType(), 0L)); | ||
| 154 | + findAndThen(userMap, libraryVO.getCreatorUserId(), user -> libraryVO.setCreatorUserName(user.getNickname())); | ||
| 155 | + return libraryVO; | ||
| 156 | + }); | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/PmsKnowledgeLibraryMemberController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.member.PmsKnowledgeLibraryMemberRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.member.PmsKnowledgeLibraryUpdateMemberListReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.library.PmsKnowledgeLibraryMemberDO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.service.kb.library.PmsKnowledgeLibraryMemberService; | ||
| 10 | +import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||
| 11 | +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||
| 12 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 13 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 14 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 15 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 16 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 17 | +import jakarta.annotation.Resource; | ||
| 18 | +import jakarta.validation.Valid; | ||
| 19 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 20 | +import org.springframework.validation.annotation.Validated; | ||
| 21 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 23 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 25 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 27 | +import org.springframework.web.bind.annotation.RestController; | ||
| 28 | + | ||
| 29 | +import java.util.Collections; | ||
| 30 | +import java.util.List; | ||
| 31 | +import java.util.Map; | ||
| 32 | + | ||
| 33 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 35 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 36 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 37 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 38 | + | ||
| 39 | +@Tag(name = "管理后台 - PMS 知识库成员") | ||
| 40 | +@RestController | ||
| 41 | +@RequestMapping("/pms/kb/library-member") | ||
| 42 | +@Validated | ||
| 43 | +public class PmsKnowledgeLibraryMemberController { | ||
| 44 | + | ||
| 45 | + @Resource | ||
| 46 | + private PmsKnowledgeLibraryMemberService memberService; | ||
| 47 | + | ||
| 48 | + @Resource | ||
| 49 | + private AdminUserApi adminUserApi; | ||
| 50 | + @Resource | ||
| 51 | + private DeptApi deptApi; | ||
| 52 | + | ||
| 53 | + @GetMapping("/list") | ||
| 54 | + @Operation(summary = "获得知识库成员列表") | ||
| 55 | + @Parameter(name = "libraryId", description = "知识库编号", required = true, example = "1024") | ||
| 56 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 57 | + public CommonResult<List<PmsKnowledgeLibraryMemberRespVO>> getLibraryMemberList(@RequestParam("libraryId") Long libraryId) { | ||
| 58 | + List<PmsKnowledgeLibraryMemberDO> members = memberService.getLibraryMemberList(libraryId, getLoginUserId()); | ||
| 59 | + return success(buildLibraryMemberRespVOList(members)); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + @PutMapping("/update-list") | ||
| 63 | + @Operation(summary = "更新知识库成员") | ||
| 64 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:update')") | ||
| 65 | + public CommonResult<Boolean> updateLibraryMemberList(@Valid @RequestBody PmsKnowledgeLibraryUpdateMemberListReqVO updateReqVO) { | ||
| 66 | + memberService.updateLibraryMemberList(updateReqVO, getLoginUserId()); | ||
| 67 | + return success(true); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + @DeleteMapping("/exit") | ||
| 71 | + @Operation(summary = "主动退出知识库") | ||
| 72 | + @Parameter(name = "libraryId", description = "知识库编号", required = true, example = "1024") | ||
| 73 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:query')") | ||
| 74 | + public CommonResult<Boolean> exitLibrary(@RequestParam("libraryId") Long libraryId) { | ||
| 75 | + memberService.exitLibrary(libraryId, getLoginUserId()); | ||
| 76 | + return success(true); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + // ==================== 拼接 VO ==================== | ||
| 80 | + | ||
| 81 | + private List<PmsKnowledgeLibraryMemberRespVO> buildLibraryMemberRespVOList( | ||
| 82 | + List<PmsKnowledgeLibraryMemberDO> members) { | ||
| 83 | + if (CollUtil.isEmpty(members)) { | ||
| 84 | + return Collections.emptyList(); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + // 1. 批量查询用户和部门 | ||
| 88 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||
| 89 | + convertSet(members, PmsKnowledgeLibraryMemberDO::getUserId)); | ||
| 90 | + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap( | ||
| 91 | + convertSet(members, PmsKnowledgeLibraryMemberDO::getDeptId)); | ||
| 92 | + Map<Long, DeptRespDTO> parentDeptMap = deptApi.getDeptMap(convertSet(deptMap.values(), DeptRespDTO::getParentId)); | ||
| 93 | + // 2. 转换成员响应,并拼接用户和部门名称 | ||
| 94 | + return convertList(members, member -> { | ||
| 95 | + PmsKnowledgeLibraryMemberRespVO memberVO = BeanUtils.toBean(member, PmsKnowledgeLibraryMemberRespVO.class); | ||
| 96 | + findAndThen(userMap, member.getUserId(), user -> | ||
| 97 | + memberVO.setNickname(user.getNickname()).setAvatar(user.getAvatar())); | ||
| 98 | + findAndThen(deptMap, member.getDeptId(), dept -> { | ||
| 99 | + memberVO.setDeptName(dept.getName()).setParentDeptId(dept.getParentId()); | ||
| 100 | + findAndThen(parentDeptMap, dept.getParentId(), parent -> memberVO.setParentDeptName(parent.getName())); | ||
| 101 | + }); | ||
| 102 | + return memberVO; | ||
| 103 | + }); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/PmsKnowledgeLibraryTemplateController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.template.PmsKnowledgeLibraryTemplatePageReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.template.PmsKnowledgeLibraryTemplateRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.template.PmsKnowledgeLibraryTemplateSaveReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.library.PmsKnowledgeLibraryTemplateDO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.service.kb.library.PmsKnowledgeLibraryTemplateService; | ||
| 12 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 13 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 14 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 15 | +import jakarta.annotation.Resource; | ||
| 16 | +import jakarta.validation.Valid; | ||
| 17 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 18 | +import org.springframework.validation.annotation.Validated; | ||
| 19 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 23 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 25 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 26 | +import org.springframework.web.bind.annotation.RestController; | ||
| 27 | + | ||
| 28 | +import java.util.List; | ||
| 29 | + | ||
| 30 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 31 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 32 | + | ||
| 33 | +/** | ||
| 34 | + * 管理后台 - PMS 知识库模板 Controller | ||
| 35 | + * | ||
| 36 | + * @author 芋道源码 | ||
| 37 | + */ | ||
| 38 | +@Tag(name = "管理后台 - PMS 知识库模板") | ||
| 39 | +@RestController | ||
| 40 | +@RequestMapping("/pms/kb/library-template") | ||
| 41 | +@Validated | ||
| 42 | +public class PmsKnowledgeLibraryTemplateController { | ||
| 43 | + | ||
| 44 | + @Resource | ||
| 45 | + private PmsKnowledgeLibraryTemplateService libraryTemplateService; | ||
| 46 | + | ||
| 47 | + @PostMapping("/create") | ||
| 48 | + @Operation(summary = "创建知识库模板") | ||
| 49 | + @PreAuthorize("@ss.hasPermission('pms:kb:library-template:create')") | ||
| 50 | + public CommonResult<Long> createLibraryTemplate( | ||
| 51 | + @Valid @RequestBody PmsKnowledgeLibraryTemplateSaveReqVO createReqVO) { | ||
| 52 | + return success(libraryTemplateService.createLibraryTemplate(createReqVO)); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @PutMapping("/update") | ||
| 56 | + @Operation(summary = "更新知识库模板") | ||
| 57 | + @PreAuthorize("@ss.hasPermission('pms:kb:library-template:update')") | ||
| 58 | + public CommonResult<Boolean> updateLibraryTemplate( | ||
| 59 | + @Valid @RequestBody PmsKnowledgeLibraryTemplateSaveReqVO updateReqVO) { | ||
| 60 | + libraryTemplateService.updateLibraryTemplate(updateReqVO); | ||
| 61 | + return success(true); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + @DeleteMapping("/delete") | ||
| 65 | + @Operation(summary = "删除知识库模板") | ||
| 66 | + @Parameter(name = "id", description = "模板编号", required = true, example = "1024") | ||
| 67 | + @PreAuthorize("@ss.hasPermission('pms:kb:library-template:delete')") | ||
| 68 | + public CommonResult<Boolean> deleteLibraryTemplate(@RequestParam("id") Long id) { | ||
| 69 | + libraryTemplateService.deleteLibraryTemplate(id); | ||
| 70 | + return success(true); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + @GetMapping("/get") | ||
| 74 | + @Operation(summary = "获得知识库模板") | ||
| 75 | + @Parameter(name = "id", description = "模板编号", required = true, example = "1024") | ||
| 76 | + @PreAuthorize("@ss.hasPermission('pms:kb:library-template:query')") | ||
| 77 | + public CommonResult<PmsKnowledgeLibraryTemplateRespVO> getLibraryTemplate(@RequestParam("id") Long id) { | ||
| 78 | + PmsKnowledgeLibraryTemplateDO template = libraryTemplateService.getLibraryTemplate(id); | ||
| 79 | + return success(BeanUtils.toBean(template, PmsKnowledgeLibraryTemplateRespVO.class)); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + @GetMapping("/simple-list") | ||
| 83 | + @Operation(summary = "获取知识库模板全列表", description = "只包含开启状态模板,返回模板选择所需的基本信息和文档标题") | ||
| 84 | + public CommonResult<List<PmsKnowledgeLibraryTemplateRespVO>> getSimpleLibraryTemplateList() { | ||
| 85 | + return success(convertList(libraryTemplateService.getLibraryTemplateList(CommonStatusEnum.ENABLE.getStatus()), | ||
| 86 | + template -> new PmsKnowledgeLibraryTemplateRespVO().setId(template.getId()) | ||
| 87 | + .setName(template.getName()).setCoverUrl(template.getCoverUrl()).setDescription(template.getDescription()) | ||
| 88 | + .setDocuments(convertList(template.getDocuments(), document -> | ||
| 89 | + new PmsKnowledgeLibraryTemplateSaveReqVO.Document().setTitle(document.getTitle()))))); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + @GetMapping("/page") | ||
| 93 | + @Operation(summary = "获得知识库模板分页") | ||
| 94 | + @PreAuthorize("@ss.hasPermission('pms:kb:library-template:query')") | ||
| 95 | + public CommonResult<PageResult<PmsKnowledgeLibraryTemplateRespVO>> getLibraryTemplatePage( | ||
| 96 | + @Valid PmsKnowledgeLibraryTemplatePageReqVO pageReqVO) { | ||
| 97 | + PageResult<PmsKnowledgeLibraryTemplateDO> pageResult = libraryTemplateService | ||
| 98 | + .getLibraryTemplatePage(pageReqVO); | ||
| 99 | + return success(new PageResult<>(BeanUtils.toBean(pageResult.getList(), PmsKnowledgeLibraryTemplateRespVO.class), | ||
| 100 | + pageResult.getTotal())); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/group/PmsKnowledgeGroupRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.group; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识库分组 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeGroupRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "知识库分组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "分组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品知识库") | ||
| 16 | + private String name; | ||
| 17 | + | ||
| 18 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 19 | + private Integer sort; | ||
| 20 | + | ||
| 21 | + @Schema(description = "分组类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 22 | + private Integer type; | ||
| 23 | + | ||
| 24 | + @Schema(description = "分组内知识库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") | ||
| 25 | + private Integer libraryCount; | ||
| 26 | + | ||
| 27 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 28 | + private LocalDateTime createTime; | ||
| 29 | + | ||
| 30 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/group/PmsKnowledgeGroupSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.group; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.Size; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识库分组新增/修改 Request VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeGroupSaveReqVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "知识库分组编号", example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "分组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品知识库") | ||
| 16 | + @NotBlank(message = "分组名称不能为空") | ||
| 17 | + @Size(max = 100, message = "分组名称不能超过 100 个字符") | ||
| 18 | + private String name; | ||
| 19 | + | ||
| 20 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/group/PmsKnowledgeGroupSortReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.group; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.Valid; | ||
| 5 | +import jakarta.validation.constraints.Min; | ||
| 6 | +import jakarta.validation.constraints.NotEmpty; | ||
| 7 | +import jakarta.validation.constraints.NotNull; | ||
| 8 | +import lombok.Data; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +@Schema(description = "管理后台 - PMS 知识库分组排序 Request VO") | ||
| 13 | +@Data | ||
| 14 | +public class PmsKnowledgeGroupSortReqVO { | ||
| 15 | + | ||
| 16 | + @Schema(description = "知识库分组排序项", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 17 | + @NotEmpty(message = "知识库分组排序项不能为空") | ||
| 18 | + private List<@Valid Item> items; | ||
| 19 | + | ||
| 20 | + @Schema(description = "管理后台 - PMS 知识库分组排序项 Request VO") | ||
| 21 | + @Data | ||
| 22 | + public static class Item { | ||
| 23 | + | ||
| 24 | + @Schema(description = "知识库分组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 25 | + @NotNull(message = "知识库分组编号不能为空") | ||
| 26 | + private Long id; | ||
| 27 | + | ||
| 28 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 29 | + @NotNull(message = "显示顺序不能为空") | ||
| 30 | + @Min(value = 0, message = "显示顺序不能小于 0") | ||
| 31 | + private Integer sort; | ||
| 32 | + | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/group/PmsKnowledgeLibraryMoveGroupReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.group; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - PMS 知识库移动分组 Request VO") | ||
| 8 | +@Data | ||
| 9 | +public class PmsKnowledgeLibraryMoveGroupReqVO { | ||
| 10 | + | ||
| 11 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 12 | + @NotNull(message = "知识库编号不能为空") | ||
| 13 | + private Long libraryId; | ||
| 14 | + | ||
| 15 | + @Schema(description = "目标分组编号;为空表示移出分组", example = "2048") | ||
| 16 | + private Long groupId; | ||
| 17 | + | ||
| 18 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/library/PmsKnowledgeLibraryPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.library; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库分页 Request VO") | ||
| 10 | +@Data | ||
| 11 | +@EqualsAndHashCode(callSuper = true) | ||
| 12 | +@ToString(callSuper = true) | ||
| 13 | +public class PmsKnowledgeLibraryPageReqVO extends PageParam { | ||
| 14 | + | ||
| 15 | + @Schema(description = "知识库名称", example = "产品") | ||
| 16 | + private String name; | ||
| 17 | + | ||
| 18 | + @Schema(description = "个人知识库分组编号", example = "1024") | ||
| 19 | + private Long groupId; | ||
| 20 | + | ||
| 21 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/library/PmsKnowledgeLibraryRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.library; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识库 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeLibraryRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品知识库") | ||
| 16 | + private String name; | ||
| 17 | + | ||
| 18 | + @Schema(description = "知识库简介") | ||
| 19 | + private String description; | ||
| 20 | + | ||
| 21 | + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 22 | + private Boolean openStatus; | ||
| 23 | + | ||
| 24 | + @Schema(description = "知识库封面") | ||
| 25 | + private String coverUrl; | ||
| 26 | + | ||
| 27 | + @Schema(description = "创建人用户编号", example = "1") | ||
| 28 | + private Long creatorUserId; | ||
| 29 | + | ||
| 30 | + @Schema(description = "创建人姓名", example = "芋道源码") | ||
| 31 | + private String creatorUserName; | ||
| 32 | + | ||
| 33 | + @Schema(description = "成员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") | ||
| 34 | + private Integer memberCount; | ||
| 35 | + | ||
| 36 | + @Schema(description = "文档数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12") | ||
| 37 | + private Long documentCount; | ||
| 38 | + | ||
| 39 | + @Schema(description = "文件数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4") | ||
| 40 | + private Long fileCount; | ||
| 41 | + | ||
| 42 | + @Schema(description = "当前用户是否可以编辑内容", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 43 | + private Boolean writeStatus; | ||
| 44 | + | ||
| 45 | + @Schema(description = "当前用户是否为知识库管理员", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 46 | + private Boolean adminStatus; | ||
| 47 | + | ||
| 48 | + @Schema(description = "当前用户是否可以主动退出知识库", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 49 | + private Boolean exitStatus; | ||
| 50 | + | ||
| 51 | + @Schema(description = "当前用户是否已关注", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 52 | + private Boolean favoriteStatus; | ||
| 53 | + | ||
| 54 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 55 | + private LocalDateTime createTime; | ||
| 56 | + | ||
| 57 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/library/PmsKnowledgeLibrarySaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.library; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 6 | +import jakarta.validation.constraints.Positive; | ||
| 7 | +import jakarta.validation.constraints.Size; | ||
| 8 | +import lombok.Data; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +@Schema(description = "管理后台 - PMS 知识库新增/修改 Request VO") | ||
| 13 | +@Data | ||
| 14 | +public class PmsKnowledgeLibrarySaveReqVO { | ||
| 15 | + | ||
| 16 | + @Schema(description = "知识库编号", example = "1024") | ||
| 17 | + private Long id; | ||
| 18 | + | ||
| 19 | + @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品知识库") | ||
| 20 | + @NotBlank(message = "知识库名称不能为空") | ||
| 21 | + @Size(max = 50, message = "知识库名称不能超过 50 个字符") | ||
| 22 | + private String name; | ||
| 23 | + | ||
| 24 | + @Schema(description = "知识库简介", example = "沉淀产品文档") | ||
| 25 | + @Size(max = 300, message = "知识库简介不能超过 300 个字符") | ||
| 26 | + private String description; | ||
| 27 | + | ||
| 28 | + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | ||
| 29 | + @NotNull(message = "知识库可见范围不能为空") | ||
| 30 | + private Boolean openStatus; | ||
| 31 | + | ||
| 32 | + @Schema(description = "知识库封面") | ||
| 33 | + @Size(max = 255, message = "知识库封面地址不能超过 255 个字符") | ||
| 34 | + private String coverUrl; | ||
| 35 | + | ||
| 36 | + @Schema(description = "创建时的初始管理员用户编号列表", example = "[1, 2]") | ||
| 37 | + private List<Long> adminUserIds; | ||
| 38 | + | ||
| 39 | + @Schema(description = "创建时的初始普通成员用户编号列表", example = "[3, 4]") | ||
| 40 | + private List<Long> memberUserIds; | ||
| 41 | + | ||
| 42 | + @Schema(description = "模板编号,仅创建时有效", example = "1") | ||
| 43 | + @Positive(message = "模板编号必须大于 0") | ||
| 44 | + private Long templateId; | ||
| 45 | + | ||
| 46 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/member/PmsKnowledgeLibraryMemberRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.member; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +@Schema(description = "管理后台 - PMS 知识库成员 Response VO") | ||
| 7 | +@Data | ||
| 8 | +public class PmsKnowledgeLibraryMemberRespVO { | ||
| 9 | + | ||
| 10 | + @Schema(description = "成员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 11 | + private Long id; | ||
| 12 | + | ||
| 13 | + @Schema(description = "用户编号", example = "1") | ||
| 14 | + private Long userId; | ||
| 15 | + | ||
| 16 | + @Schema(description = "用户姓名", example = "芋道源码") | ||
| 17 | + private String nickname; | ||
| 18 | + | ||
| 19 | + @Schema(description = "用户头像") | ||
| 20 | + private String avatar; | ||
| 21 | + | ||
| 22 | + @Schema(description = "部门编号", example = "100") | ||
| 23 | + private Long deptId; | ||
| 24 | + | ||
| 25 | + @Schema(description = "部门名称", example = "研发部") | ||
| 26 | + private String deptName; | ||
| 27 | + | ||
| 28 | + @Schema(description = "父部门编号") | ||
| 29 | + private Long parentDeptId; | ||
| 30 | + | ||
| 31 | + @Schema(description = "父部门名称") | ||
| 32 | + private String parentDeptName; | ||
| 33 | + | ||
| 34 | + @Schema(description = "成员等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 35 | + private Integer level; | ||
| 36 | + | ||
| 37 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/member/PmsKnowledgeLibraryUpdateMemberListReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.member; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 4 | +import cn.iocoder.yudao.module.pms.enums.kb.library.PmsKnowledgeLibraryMemberLevelEnum; | ||
| 5 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 7 | +import jakarta.validation.Valid; | ||
| 8 | +import jakarta.validation.constraints.AssertTrue; | ||
| 9 | +import jakarta.validation.constraints.NotNull; | ||
| 10 | +import lombok.Data; | ||
| 11 | + | ||
| 12 | +import java.util.List; | ||
| 13 | + | ||
| 14 | +@Schema(description = "管理后台 - PMS 更新知识库成员列表 Request VO") | ||
| 15 | +@Data | ||
| 16 | +public class PmsKnowledgeLibraryUpdateMemberListReqVO { | ||
| 17 | + | ||
| 18 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 19 | + @NotNull(message = "知识库编号不能为空") | ||
| 20 | + private Long libraryId; | ||
| 21 | + | ||
| 22 | + @Schema(description = "成员列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 23 | + @Valid | ||
| 24 | + @NotNull(message = "成员列表不能为空") | ||
| 25 | + private List<Member> members; | ||
| 26 | + | ||
| 27 | + @Schema(description = "管理后台 - PMS 知识库成员更新项") | ||
| 28 | + @Data | ||
| 29 | + public static class Member { | ||
| 30 | + | ||
| 31 | + @Schema(description = "用户编号", example = "1") | ||
| 32 | + private Long userId; | ||
| 33 | + | ||
| 34 | + @Schema(description = "部门编号", example = "100") | ||
| 35 | + private Long deptId; | ||
| 36 | + | ||
| 37 | + @Schema(description = "成员等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 38 | + @NotNull(message = "成员等级不能为空") | ||
| 39 | + @InEnum(PmsKnowledgeLibraryMemberLevelEnum.class) | ||
| 40 | + private Integer level; | ||
| 41 | + | ||
| 42 | + @AssertTrue(message = "知识库成员必须且只能选择用户或部门") | ||
| 43 | + @JsonIgnore | ||
| 44 | + public boolean isUserOrDeptValid() { | ||
| 45 | + return (userId != null && deptId == null) || (userId == null && deptId != null); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/template/PmsKnowledgeLibraryTemplatePageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.template; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 5 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - PMS 知识库模板分页 Request VO") | ||
| 11 | +@Data | ||
| 12 | +@EqualsAndHashCode(callSuper = true) | ||
| 13 | +public class PmsKnowledgeLibraryTemplatePageReqVO extends PageParam { | ||
| 14 | + | ||
| 15 | + @Schema(description = "模板名称,模糊匹配", example = "产品研发") | ||
| 16 | + private String name; | ||
| 17 | + | ||
| 18 | + @Schema(description = "模板状态", example = "0") | ||
| 19 | + @InEnum(CommonStatusEnum.class) | ||
| 20 | + private Integer status; | ||
| 21 | + | ||
| 22 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/template/PmsKnowledgeLibraryTemplateRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.template; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库模板 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeLibraryTemplateRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品研发") | ||
| 17 | + private String name; | ||
| 18 | + | ||
| 19 | + @Schema(description = "模板简介", example = "提供完善的产品流程文档") | ||
| 20 | + private String description; | ||
| 21 | + | ||
| 22 | + @Schema(description = "模板封面地址", example = "/static/pms/kb/template/product.png") | ||
| 23 | + private String coverUrl; | ||
| 24 | + | ||
| 25 | + @Schema(description = "模板状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||
| 26 | + private Integer status; | ||
| 27 | + | ||
| 28 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 29 | + private Integer sort; | ||
| 30 | + | ||
| 31 | + @Schema(description = "模板文档列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 32 | + private List<PmsKnowledgeLibraryTemplateSaveReqVO.Document> documents; | ||
| 33 | + | ||
| 34 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 35 | + private LocalDateTime createTime; | ||
| 36 | + | ||
| 37 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/library/vo/template/PmsKnowledgeLibraryTemplateSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.library.vo.template; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import jakarta.validation.Valid; | ||
| 7 | +import jakarta.validation.constraints.NotBlank; | ||
| 8 | +import jakarta.validation.constraints.NotEmpty; | ||
| 9 | +import jakarta.validation.constraints.NotNull; | ||
| 10 | +import jakarta.validation.constraints.PositiveOrZero; | ||
| 11 | +import jakarta.validation.constraints.Size; | ||
| 12 | +import lombok.Data; | ||
| 13 | + | ||
| 14 | +import java.util.List; | ||
| 15 | + | ||
| 16 | +@Schema(description = "管理后台 - PMS 知识库模板新增/修改 Request VO") | ||
| 17 | +@Data | ||
| 18 | +public class PmsKnowledgeLibraryTemplateSaveReqVO { | ||
| 19 | + | ||
| 20 | + @Schema(description = "模板编号", example = "1024") | ||
| 21 | + private Long id; | ||
| 22 | + | ||
| 23 | + @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品研发") | ||
| 24 | + @NotBlank(message = "模板名称不能为空") | ||
| 25 | + @Size(max = 100, message = "模板名称不能超过 100 个字符") | ||
| 26 | + private String name; | ||
| 27 | + | ||
| 28 | + @Schema(description = "模板简介", example = "提供完善的产品流程文档") | ||
| 29 | + @Size(max = 500, message = "模板简介不能超过 500 个字符") | ||
| 30 | + private String description; | ||
| 31 | + | ||
| 32 | + @Schema(description = "模板封面地址", example = "/static/pms/kb/template/product.png") | ||
| 33 | + @Size(max = 255, message = "模板封面地址不能超过 255 个字符") | ||
| 34 | + private String coverUrl; | ||
| 35 | + | ||
| 36 | + @Schema(description = "模板状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||
| 37 | + @NotNull(message = "模板状态不能为空") | ||
| 38 | + @InEnum(CommonStatusEnum.class) | ||
| 39 | + private Integer status; | ||
| 40 | + | ||
| 41 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 42 | + @NotNull(message = "显示顺序不能为空") | ||
| 43 | + @PositiveOrZero(message = "显示顺序不能小于 0") | ||
| 44 | + private Integer sort; | ||
| 45 | + | ||
| 46 | + @Schema(description = "模板文档列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 47 | + @NotEmpty(message = "模板文档不能为空") | ||
| 48 | + @Valid | ||
| 49 | + private List<Document> documents; | ||
| 50 | + | ||
| 51 | + @Schema(description = "模板文档") | ||
| 52 | + @Data | ||
| 53 | + public static class Document { | ||
| 54 | + | ||
| 55 | + @Schema(description = "文档标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品需求文档") | ||
| 56 | + @NotBlank(message = "文档标题不能为空") | ||
| 57 | + @Size(max = 255, message = "文档标题不能超过 255 个字符") | ||
| 58 | + private String title; | ||
| 59 | + | ||
| 60 | + @Schema(description = "文档内容", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 61 | + @NotBlank(message = "文档内容不能为空") | ||
| 62 | + private String content; | ||
| 63 | + | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/recycle/PmsKnowledgeRecycleController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.recycle; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.recycle.vo.PmsKnowledgeRecycleDetailRespVO; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.recycle.vo.PmsKnowledgeRecyclePreviewRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.kb.recycle.vo.PmsKnowledgeRecycleRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.content.PmsKnowledgeDocumentDO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.dal.dataobject.kb.recycle.PmsKnowledgeRecycleRecordDO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.enums.kb.PmsKnowledgeObjectTypeEnum; | ||
| 11 | +import cn.iocoder.yudao.module.pms.service.kb.content.PmsKnowledgeDocumentService; | ||
| 12 | +import cn.iocoder.yudao.module.pms.service.kb.recycle.PmsKnowledgeRecycleService; | ||
| 13 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 14 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 15 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 16 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 17 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 18 | +import jakarta.annotation.Resource; | ||
| 19 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 20 | +import org.springframework.validation.annotation.Validated; | ||
| 21 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 23 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 25 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 26 | +import org.springframework.web.bind.annotation.RestController; | ||
| 27 | + | ||
| 28 | +import java.util.List; | ||
| 29 | +import java.util.Map; | ||
| 30 | + | ||
| 31 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 32 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 33 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 34 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 35 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 36 | + | ||
| 37 | +@Tag(name = "管理后台 - PMS 知识库回收站") | ||
| 38 | +@RestController | ||
| 39 | +@RequestMapping("/pms/kb/recycle") | ||
| 40 | +@Validated | ||
| 41 | +public class PmsKnowledgeRecycleController { | ||
| 42 | + | ||
| 43 | + @Resource | ||
| 44 | + private PmsKnowledgeRecycleService recycleService; | ||
| 45 | + | ||
| 46 | + @Resource | ||
| 47 | + private AdminUserApi adminUserApi; | ||
| 48 | + | ||
| 49 | + @Resource | ||
| 50 | + private PmsKnowledgeDocumentService documentService; | ||
| 51 | + | ||
| 52 | + @GetMapping("/library-list") | ||
| 53 | + @Operation(summary = "获得已删除知识库列表") | ||
| 54 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 55 | + public CommonResult<List<PmsKnowledgeRecycleRespVO>> getLibraryRecycleList() { | ||
| 56 | + List<PmsKnowledgeRecycleRecordDO> records = recycleService.getLibraryRecycleList(getLoginUserId()); | ||
| 57 | + return success(buildRecycleRespVOList(records)); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + @GetMapping("/content-list") | ||
| 61 | + @Operation(summary = "获得知识库最近删除内容") | ||
| 62 | + @Parameter(name = "libraryId", description = "知识库编号", required = true, example = "1024") | ||
| 63 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 64 | + public CommonResult<List<PmsKnowledgeRecycleRespVO>> getContentRecycleList( | ||
| 65 | + @RequestParam("libraryId") Long libraryId) { | ||
| 66 | + List<PmsKnowledgeRecycleRecordDO> records = recycleService.getContentRecycleList( | ||
| 67 | + libraryId, getLoginUserId()); | ||
| 68 | + return success(buildRecycleRespVOList(records)); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + @GetMapping("/content-detail") | ||
| 72 | + @Operation(summary = "获得知识库最近删除详情") | ||
| 73 | + @Parameter(name = "id", description = "回收站记录编号", required = true, example = "1024") | ||
| 74 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 75 | + public CommonResult<PmsKnowledgeRecycleDetailRespVO> getContentRecycleDetail( | ||
| 76 | + @RequestParam("id") Long id) { | ||
| 77 | + return success(recycleService.getContentRecycleDetail(id, getLoginUserId())); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + @GetMapping("/content-preview") | ||
| 81 | + @Operation(summary = "预览知识库最近删除内容") | ||
| 82 | + @Parameter(name = "id", description = "回收站记录编号", required = true, example = "1024") | ||
| 83 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 84 | + public CommonResult<PmsKnowledgeRecyclePreviewRespVO> getContentRecyclePreview( | ||
| 85 | + @RequestParam("id") Long id, | ||
| 86 | + @RequestParam(value = "entityId", required = false) Long entityId) { | ||
| 87 | + PmsKnowledgeDocumentDO document = recycleService.getContentRecyclePreview(id, entityId, getLoginUserId()); | ||
| 88 | + return success(BeanUtils.toBean(document, PmsKnowledgeRecyclePreviewRespVO.class, | ||
| 89 | + o -> o.setName(document.getTitle()))); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + @PutMapping("/restore") | ||
| 93 | + @Operation(summary = "恢复回收站对象") | ||
| 94 | + @Parameter(name = "id", description = "回收站记录编号", required = true, example = "1024") | ||
| 95 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 96 | + public CommonResult<Boolean> restoreContentRecycle(@RequestParam("id") Long id) { | ||
| 97 | + recycleService.restoreContentRecycle(id, getLoginUserId()); | ||
| 98 | + return success(true); | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + @DeleteMapping("/permanent-delete") | ||
| 102 | + @Operation(summary = "彻底删除回收站对象") | ||
| 103 | + @Parameter(name = "id", description = "回收站记录编号", required = true, example = "1024") | ||
| 104 | + @PreAuthorize("@ss.hasPermission('pms:kb:library:delete')") | ||
| 105 | + public CommonResult<Boolean> deleteContentRecycle(@RequestParam("id") Long id) { | ||
| 106 | + recycleService.deleteContentRecycle(id, getLoginUserId()); | ||
| 107 | + return success(true); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + // ==================== 拼接 VO ==================== | ||
| 111 | + | ||
| 112 | + private List<PmsKnowledgeRecycleRespVO> buildRecycleRespVOList(List<PmsKnowledgeRecycleRecordDO> records) { | ||
| 113 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||
| 114 | + convertSet(records, PmsKnowledgeRecycleRecordDO::getDeleteUserId)); | ||
| 115 | + Map<Long, PmsKnowledgeDocumentDO> documentMap = documentService.getDocumentMap(convertSet(records, record -> | ||
| 116 | + PmsKnowledgeObjectTypeEnum.FILE.getType().equals(record.getType()) ? record.getEntityId() : null)); | ||
| 117 | + return convertList(records, record -> { | ||
| 118 | + PmsKnowledgeRecycleRespVO recordVO = BeanUtils.toBean(record, PmsKnowledgeRecycleRespVO.class); | ||
| 119 | + findAndThen(documentMap, record.getEntityId(), document -> recordVO.setFileSize(document.getFileSize())); | ||
| 120 | + findAndThen(userMap, record.getDeleteUserId(), user -> recordVO.setDeleteUserName(user.getNickname())); | ||
| 121 | + return recordVO; | ||
| 122 | + }); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/recycle/vo/PmsKnowledgeRecycleDetailRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.recycle.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 知识库回收站详情 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsKnowledgeRecycleDetailRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "根回收站记录") | ||
| 14 | + private PmsKnowledgeRecycleRespVO root; | ||
| 15 | + | ||
| 16 | + @Schema(description = "级联删除内容") | ||
| 17 | + private List<Item> children; | ||
| 18 | + | ||
| 19 | + @Data | ||
| 20 | + public static class Item { | ||
| 21 | + | ||
| 22 | + @Schema(description = "内容编号", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 23 | + private Long id; | ||
| 24 | + | ||
| 25 | + @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 26 | + private Integer type; | ||
| 27 | + | ||
| 28 | + @Schema(description = "内容名称", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 29 | + private String name; | ||
| 30 | + | ||
| 31 | + @Schema(description = "父文档或父文件夹编号") | ||
| 32 | + private Long parentId; | ||
| 33 | + | ||
| 34 | + @Schema(description = "所属文件夹编号") | ||
| 35 | + private Long folderId; | ||
| 36 | + | ||
| 37 | + @Schema(description = "删除时间") | ||
| 38 | + private LocalDateTime deleteTime; | ||
| 39 | + | ||
| 40 | + } | ||
| 41 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/recycle/vo/PmsKnowledgeRecyclePreviewRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.recycle.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +@Schema(description = "管理后台 - PMS 知识库回收站内容预览 Response VO") | ||
| 7 | +@Data | ||
| 8 | +public class PmsKnowledgeRecyclePreviewRespVO { | ||
| 9 | + | ||
| 10 | + @Schema(description = "内容编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 11 | + private Long id; | ||
| 12 | + | ||
| 13 | + @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 14 | + private Integer type; | ||
| 15 | + | ||
| 16 | + @Schema(description = "内容名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品说明") | ||
| 17 | + private String name; | ||
| 18 | + | ||
| 19 | + @Schema(description = "文档正文或文件地址") | ||
| 20 | + private String content; | ||
| 21 | + | ||
| 22 | + @Schema(description = "文件类型", example = "pdf") | ||
| 23 | + private String fileType; | ||
| 24 | + | ||
| 25 | + @Schema(description = "文件大小,单位:字节", example = "102400") | ||
| 26 | + private Long fileSize; | ||
| 27 | + | ||
| 28 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/kb/recycle/vo/PmsKnowledgeRecycleRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.kb.recycle.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 知识库回收站记录 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsKnowledgeRecycleRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "回收站记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 16 | + private Long libraryId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "对象类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 19 | + private Integer type; | ||
| 20 | + | ||
| 21 | + @Schema(description = "对象编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | ||
| 22 | + private Long entityId; | ||
| 23 | + | ||
| 24 | + @Schema(description = "对象名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品说明") | ||
| 25 | + private String name; | ||
| 26 | + | ||
| 27 | + @Schema(description = "文件大小,单位:字节") | ||
| 28 | + private Long fileSize; | ||
| 29 | + | ||
| 30 | + @Schema(description = "删除人用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 31 | + private Long deleteUserId; | ||
| 32 | + | ||
| 33 | + @Schema(description = "删除人姓名", example = "芋道") | ||
| 34 | + private String deleteUserName; | ||
| 35 | + | ||
| 36 | + @Schema(description = "删除时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 37 | + private LocalDateTime deleteTime; | ||
| 38 | + | ||
| 39 | + @Schema(description = "父对象编号,回收站详情中用于组装层级", example = "2048") | ||
| 40 | + private Long parentId; | ||
| 41 | + | ||
| 42 | + @Schema(description = "所属文件夹编号,回收站详情中用于组装层级", example = "2048") | ||
| 43 | + private Long folderId; | ||
| 44 | + | ||
| 45 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/iteration/PmsIterationController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.iteration; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo.PmsIterationOverviewRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo.PmsIterationPageReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo.PmsIterationRespVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo.PmsIterationSaveReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo.PmsIterationStartReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.iteration.PmsIterationDO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.service.pm.iteration.PmsIterationService; | ||
| 14 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 15 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 16 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 17 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 18 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 19 | +import jakarta.annotation.Resource; | ||
| 20 | +import jakarta.validation.Valid; | ||
| 21 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 22 | +import org.springframework.validation.annotation.Validated; | ||
| 23 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 25 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 27 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 28 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 29 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 30 | +import org.springframework.web.bind.annotation.RestController; | ||
| 31 | + | ||
| 32 | +import java.util.Collections; | ||
| 33 | +import java.util.List; | ||
| 34 | +import java.util.Map; | ||
| 35 | + | ||
| 36 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 37 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 38 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 39 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 40 | + | ||
| 41 | +@Tag(name = "管理后台 - PMS 项目迭代") | ||
| 42 | +@RestController | ||
| 43 | +@RequestMapping("/pms/pm/iteration") | ||
| 44 | +@Validated | ||
| 45 | +public class PmsIterationController { | ||
| 46 | + | ||
| 47 | + @Resource | ||
| 48 | + private PmsIterationService iterationService; | ||
| 49 | + | ||
| 50 | + @Resource | ||
| 51 | + private AdminUserApi adminUserApi; | ||
| 52 | + | ||
| 53 | + @PostMapping("/create") | ||
| 54 | + @Operation(summary = "创建项目迭代") | ||
| 55 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:create')") | ||
| 56 | + public CommonResult<Long> createIteration(@Valid @RequestBody PmsIterationSaveReqVO saveReqVO) { | ||
| 57 | + return success(iterationService.createIteration(saveReqVO, getLoginUserId())); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + @PutMapping("/update") | ||
| 61 | + @Operation(summary = "更新项目迭代") | ||
| 62 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:update')") | ||
| 63 | + public CommonResult<Boolean> updateIteration(@Valid @RequestBody PmsIterationSaveReqVO saveReqVO) { | ||
| 64 | + iterationService.updateIteration(saveReqVO, getLoginUserId()); | ||
| 65 | + return success(true); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + @PutMapping("/start") | ||
| 69 | + @Operation(summary = "开始项目迭代") | ||
| 70 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:update')") | ||
| 71 | + public CommonResult<Boolean> startIteration(@Valid @RequestBody PmsIterationStartReqVO startReqVO) { | ||
| 72 | + iterationService.startIteration(startReqVO, getLoginUserId()); | ||
| 73 | + return success(true); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @PutMapping("/complete") | ||
| 77 | + @Operation(summary = "完成项目迭代") | ||
| 78 | + @Parameter(name = "id", description = "迭代编号", required = true, example = "1024") | ||
| 79 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:update')") | ||
| 80 | + public CommonResult<Boolean> completeIteration(@RequestParam("id") Long id) { | ||
| 81 | + iterationService.completeIteration(id, getLoginUserId()); | ||
| 82 | + return success(true); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + @DeleteMapping("/delete") | ||
| 86 | + @Operation(summary = "删除项目迭代") | ||
| 87 | + @Parameter(name = "id", description = "迭代编号", required = true, example = "1024") | ||
| 88 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:delete')") | ||
| 89 | + public CommonResult<Boolean> deleteIteration(@RequestParam("id") Long id) { | ||
| 90 | + iterationService.deleteIteration(id, getLoginUserId()); | ||
| 91 | + return success(true); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @GetMapping("/get") | ||
| 95 | + @Operation(summary = "获得项目迭代详情") | ||
| 96 | + @Parameter(name = "id", description = "迭代编号", required = true, example = "1024") | ||
| 97 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:query')") | ||
| 98 | + public CommonResult<PmsIterationRespVO> getIteration(@RequestParam("id") Long id) { | ||
| 99 | + PmsIterationDO iteration = iterationService.getIteration(id, getLoginUserId()); | ||
| 100 | + PmsIterationRespVO iterationVO = buildIterationRespVO(iteration); | ||
| 101 | + return success(iterationVO); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + @GetMapping("/page") | ||
| 105 | + @Operation(summary = "获得项目迭代分页") | ||
| 106 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:query')") | ||
| 107 | + public CommonResult<PageResult<PmsIterationRespVO>> getIterationPage( | ||
| 108 | + @Valid PmsIterationPageReqVO pageReqVO) { | ||
| 109 | + PageResult<PmsIterationDO> pageResult = iterationService.getIterationPage(pageReqVO, getLoginUserId()); | ||
| 110 | + List<PmsIterationRespVO> iterationVOList = buildIterationRespVOList(pageResult.getList()); | ||
| 111 | + Map<Long, Integer> progressMap = iterationService.getIterationProgressMap( | ||
| 112 | + convertSet(pageResult.getList(), PmsIterationDO::getId)); | ||
| 113 | + iterationVOList.forEach(iteration -> iteration.setProgress(progressMap.getOrDefault(iteration.getId(), 0))); | ||
| 114 | + return success(new PageResult<>(iterationVOList, pageResult.getTotal())); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + @GetMapping("/overview") | ||
| 118 | + @Operation(summary = "获得迭代概览统计") | ||
| 119 | + @Parameter(name = "id", description = "迭代编号", required = true, example = "1024") | ||
| 120 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:query')") | ||
| 121 | + public CommonResult<PmsIterationOverviewRespVO> getIterationOverview(@RequestParam("id") Long id) { | ||
| 122 | + PmsIterationOverviewRespVO overview = iterationService.getIterationOverview(id, getLoginUserId()); | ||
| 123 | + List<PmsIterationOverviewRespVO.ActivityItem> activities = overview.getRecentActivities(); | ||
| 124 | + Map<Long, AdminUserRespDTO> activityUserMap = adminUserApi.getUserMap( | ||
| 125 | + convertSet(activities, PmsIterationOverviewRespVO.ActivityItem::getOperatorUserId)); | ||
| 126 | + activities.forEach(activity -> findAndThen(activityUserMap, activity.getOperatorUserId(), | ||
| 127 | + user -> activity.setOperatorUserName(user.getNickname()))); | ||
| 128 | + return success(overview.setRecentActivities(activities)); | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + // ==================== 拼接 VO ==================== | ||
| 132 | + | ||
| 133 | + private PmsIterationRespVO buildIterationRespVO(PmsIterationDO iteration) { | ||
| 134 | + return CollUtil.getFirst(buildIterationRespVOList(Collections.singletonList(iteration))); | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + private List<PmsIterationRespVO> buildIterationRespVOList(List<PmsIterationDO> iterations) { | ||
| 138 | + if (CollUtil.isEmpty(iterations)) { | ||
| 139 | + return Collections.emptyList(); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + // 1. 批量查询负责人 | ||
| 143 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||
| 144 | + convertSet(iterations, PmsIterationDO::getOwnerUserId)); | ||
| 145 | + | ||
| 146 | + // 2. 转换迭代响应,并拼接负责人姓名 | ||
| 147 | + return BeanUtils.toBean(iterations, PmsIterationRespVO.class, iterationVO -> | ||
| 148 | + findAndThen(userMap, iterationVO.getOwnerUserId(), | ||
| 149 | + user -> iterationVO.setOwnerUserName(user.getNickname()))); | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/iteration/vo/PmsIterationOverviewRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | +import java.util.Map; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - PMS 迭代概览 Response VO") | ||
| 11 | +@Data | ||
| 12 | +public class PmsIterationOverviewRespVO { | ||
| 13 | + | ||
| 14 | + @Schema(description = "工作项总数", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | ||
| 15 | + private Integer totalCount; | ||
| 16 | + | ||
| 17 | + @Schema(description = "未开始工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") | ||
| 18 | + private Integer pendingCount; | ||
| 19 | + | ||
| 20 | + @Schema(description = "进行中工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") | ||
| 21 | + private Integer processingCount; | ||
| 22 | + | ||
| 23 | + @Schema(description = "已完成工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") | ||
| 24 | + private Integer completedCount; | ||
| 25 | + | ||
| 26 | + @Schema(description = "完成进度百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") | ||
| 27 | + private Integer progress; | ||
| 28 | + | ||
| 29 | + @Schema(description = "工作项类型数量统计", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"1\": 60, \"2\": 40}") | ||
| 30 | + private Map<Integer, Integer> typeCountMap; | ||
| 31 | + | ||
| 32 | + @Schema(description = "工作项类型和状态数量统计", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 33 | + private Map<Integer, Map<Integer, Integer>> typeStatusCountMap; | ||
| 34 | + | ||
| 35 | + @Schema(description = "状态趋势", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 36 | + private List<TrendItem> statusTrends; | ||
| 37 | + | ||
| 38 | + @Schema(description = "燃尽图数据", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 39 | + private List<BurnDownItem> burnDowns; | ||
| 40 | + | ||
| 41 | + @Schema(description = "最近动态列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 42 | + private List<ActivityItem> recentActivities; | ||
| 43 | + | ||
| 44 | + @Schema(description = "管理后台 - PMS 迭代概览状态趋势项 VO") | ||
| 45 | + @Data | ||
| 46 | + public static class TrendItem { | ||
| 47 | + | ||
| 48 | + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-01-01") | ||
| 49 | + private String date; | ||
| 50 | + | ||
| 51 | + @Schema(description = "当日未开始工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") | ||
| 52 | + private Integer pendingCount; | ||
| 53 | + | ||
| 54 | + @Schema(description = "当日进行中工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 55 | + private Integer processingCount; | ||
| 56 | + | ||
| 57 | + @Schema(description = "当日已完成工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 58 | + private Integer completedCount; | ||
| 59 | + | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + @Schema(description = "管理后台 - PMS 迭代概览燃尽图项 VO") | ||
| 63 | + @Data | ||
| 64 | + public static class BurnDownItem { | ||
| 65 | + | ||
| 66 | + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-01-01") | ||
| 67 | + private String date; | ||
| 68 | + | ||
| 69 | + @Schema(description = "理想剩余工时,单位:小时", requiredMode = Schema.RequiredMode.REQUIRED, example = "40") | ||
| 70 | + private Integer idealRemaining; | ||
| 71 | + | ||
| 72 | + @Schema(description = "实际剩余工时,单位:小时", requiredMode = Schema.RequiredMode.REQUIRED, example = "38") | ||
| 73 | + private Integer actualRemaining; | ||
| 74 | + | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Schema(description = "管理后台 - PMS 迭代概览动态项 VO") | ||
| 78 | + @Data | ||
| 79 | + public static class ActivityItem { | ||
| 80 | + | ||
| 81 | + @Schema(description = "动态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 82 | + private Long id; | ||
| 83 | + | ||
| 84 | + @Schema(description = "工作项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 85 | + private Long workItemId; | ||
| 86 | + | ||
| 87 | + @Schema(description = "工作项序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 88 | + private Integer workItemSerialNumber; | ||
| 89 | + | ||
| 90 | + @Schema(description = "工作项名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "优化登录页") | ||
| 91 | + private String workItemName; | ||
| 92 | + | ||
| 93 | + @Schema(description = "操作人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 94 | + private Long operatorUserId; | ||
| 95 | + | ||
| 96 | + @Schema(description = "操作人昵称", example = "芋道") | ||
| 97 | + private String operatorUserName; | ||
| 98 | + | ||
| 99 | + @Schema(description = "动态内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "将状态更新为「已完成」") | ||
| 100 | + private String content; | ||
| 101 | + | ||
| 102 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 103 | + private LocalDateTime createTime; | ||
| 104 | + | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/iteration/vo/PmsIterationPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import cn.iocoder.yudao.module.pms.enums.pm.iteration.PmsIterationStatusEnum; | ||
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 7 | +import jakarta.validation.constraints.NotNull; | ||
| 8 | +import lombok.Data; | ||
| 9 | +import lombok.EqualsAndHashCode; | ||
| 10 | +import lombok.ToString; | ||
| 11 | + | ||
| 12 | +@Schema(description = "管理后台 - PMS 项目迭代分页 Request VO") | ||
| 13 | +@Data | ||
| 14 | +@EqualsAndHashCode(callSuper = true) | ||
| 15 | +@ToString(callSuper = true) | ||
| 16 | +public class PmsIterationPageReqVO extends PageParam { | ||
| 17 | + | ||
| 18 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 19 | + @NotNull(message = "项目编号不能为空") | ||
| 20 | + private Long projectId; | ||
| 21 | + | ||
| 22 | + @Schema(description = "迭代名称", example = "第一期") | ||
| 23 | + private String name; | ||
| 24 | + | ||
| 25 | + @Schema(description = "迭代状态", example = "1") | ||
| 26 | + @InEnum(PmsIterationStatusEnum.class) | ||
| 27 | + private Integer status; | ||
| 28 | + | ||
| 29 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/iteration/vo/PmsIterationRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 项目迭代 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsIterationRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "迭代编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 16 | + private Long projectId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "迭代名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "第一期") | ||
| 19 | + private String name; | ||
| 20 | + | ||
| 21 | + @Schema(description = "负责人用户编号", example = "1") | ||
| 22 | + private Long ownerUserId; | ||
| 23 | + | ||
| 24 | + @Schema(description = "迭代状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 25 | + private Integer status; | ||
| 26 | + | ||
| 27 | + @Schema(description = "负责人姓名", example = "芋道源码") | ||
| 28 | + private String ownerUserName; | ||
| 29 | + | ||
| 30 | + @Schema(description = "开始时间") | ||
| 31 | + private LocalDateTime startTime; | ||
| 32 | + | ||
| 33 | + @Schema(description = "结束时间") | ||
| 34 | + private LocalDateTime endTime; | ||
| 35 | + | ||
| 36 | + @Schema(description = "迭代目标", example = "完成核心流程") | ||
| 37 | + private String target; | ||
| 38 | + | ||
| 39 | + @Schema(description = "迭代描述") | ||
| 40 | + private String description; | ||
| 41 | + | ||
| 42 | + @Schema(description = "完成时间") | ||
| 43 | + private LocalDateTime finishTime; | ||
| 44 | + | ||
| 45 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 46 | + private Integer sort; | ||
| 47 | + | ||
| 48 | + @Schema(description = "完成进度百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") | ||
| 49 | + private Integer progress; | ||
| 50 | + | ||
| 51 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 52 | + private LocalDateTime createTime; | ||
| 53 | + | ||
| 54 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/iteration/vo/PmsIterationSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import jakarta.validation.constraints.AssertTrue; | ||
| 6 | +import jakarta.validation.constraints.NotBlank; | ||
| 7 | +import jakarta.validation.constraints.NotNull; | ||
| 8 | +import jakarta.validation.constraints.Size; | ||
| 9 | +import lombok.Data; | ||
| 10 | + | ||
| 11 | +import java.time.LocalDateTime; | ||
| 12 | + | ||
| 13 | +@Schema(description = "管理后台 - PMS 项目迭代新增/修改 Request VO") | ||
| 14 | +@Data | ||
| 15 | +public class PmsIterationSaveReqVO { | ||
| 16 | + | ||
| 17 | + @Schema(description = "迭代编号", example = "1024") | ||
| 18 | + private Long id; | ||
| 19 | + | ||
| 20 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 21 | + @NotNull(message = "项目编号不能为空") | ||
| 22 | + private Long projectId; | ||
| 23 | + | ||
| 24 | + @Schema(description = "迭代名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "第一期") | ||
| 25 | + @NotBlank(message = "迭代名称不能为空") | ||
| 26 | + @Size(max = 100, message = "迭代名称长度不能超过 100 个字符") | ||
| 27 | + private String name; | ||
| 28 | + | ||
| 29 | + @Schema(description = "负责人用户编号", example = "1") | ||
| 30 | + private Long ownerUserId; | ||
| 31 | + | ||
| 32 | + @Schema(description = "开始时间") | ||
| 33 | + private LocalDateTime startTime; | ||
| 34 | + | ||
| 35 | + @Schema(description = "结束时间") | ||
| 36 | + private LocalDateTime endTime; | ||
| 37 | + | ||
| 38 | + @Schema(description = "迭代目标", example = "完成核心流程") | ||
| 39 | + @Size(max = 255, message = "迭代目标长度不能超过 255 个字符") | ||
| 40 | + private String target; | ||
| 41 | + | ||
| 42 | + @Schema(description = "迭代描述") | ||
| 43 | + private String description; | ||
| 44 | + | ||
| 45 | + @Schema(hidden = true) | ||
| 46 | + @AssertTrue(message = "迭代结束时间必须晚于开始时间,且开始、结束时间需要同时填写") | ||
| 47 | + @JsonIgnore | ||
| 48 | + public boolean isTimeRangeValid() { | ||
| 49 | + return startTime == null && endTime == null | ||
| 50 | + || startTime != null && endTime != null && endTime.isAfter(startTime); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/iteration/vo/PmsIterationStartReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.iteration.vo; | ||
| 2 | + | ||
| 3 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import jakarta.validation.constraints.AssertTrue; | ||
| 6 | +import jakarta.validation.constraints.NotNull; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | + | ||
| 11 | +@Schema(description = "管理后台 - PMS 项目迭代开始 Request VO") | ||
| 12 | +@Data | ||
| 13 | +public class PmsIterationStartReqVO { | ||
| 14 | + | ||
| 15 | + @Schema(description = "迭代编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 16 | + @NotNull(message = "迭代编号不能为空") | ||
| 17 | + private Long id; | ||
| 18 | + | ||
| 19 | + @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 20 | + @NotNull(message = "迭代开始时间不能为空") | ||
| 21 | + private LocalDateTime startTime; | ||
| 22 | + | ||
| 23 | + @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 24 | + @NotNull(message = "迭代结束时间不能为空") | ||
| 25 | + private LocalDateTime endTime; | ||
| 26 | + | ||
| 27 | + @Schema(hidden = true) | ||
| 28 | + @AssertTrue(message = "迭代结束时间必须晚于开始时间") | ||
| 29 | + @JsonIgnore | ||
| 30 | + public boolean isTimeRangeValid() { | ||
| 31 | + return startTime == null || endTime == null || endTime.isAfter(startTime); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/PmsProjectAnnouncementController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.announcement.PmsProjectAnnouncementRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.announcement.PmsProjectAnnouncementSaveReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.project.PmsProjectAnnouncementDO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectAnnouncementService; | ||
| 11 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 12 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 13 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 14 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 15 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 16 | +import jakarta.annotation.Resource; | ||
| 17 | +import jakarta.validation.Valid; | ||
| 18 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 19 | +import org.springframework.validation.annotation.Validated; | ||
| 20 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 23 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 25 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 27 | +import org.springframework.web.bind.annotation.RestController; | ||
| 28 | + | ||
| 29 | +import java.util.Collections; | ||
| 30 | +import java.util.List; | ||
| 31 | +import java.util.Map; | ||
| 32 | + | ||
| 33 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 35 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 36 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 37 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 38 | + | ||
| 39 | +@Tag(name = "管理后台 - PMS 项目公告") | ||
| 40 | +@RestController | ||
| 41 | +@RequestMapping("/pms/pm/project-announcement") | ||
| 42 | +@Validated | ||
| 43 | +public class PmsProjectAnnouncementController { | ||
| 44 | + | ||
| 45 | + @Resource | ||
| 46 | + private PmsProjectAnnouncementService projectAnnouncementService; | ||
| 47 | + @Resource | ||
| 48 | + private AdminUserApi adminUserApi; | ||
| 49 | + | ||
| 50 | + @PostMapping("/create") | ||
| 51 | + @Operation(summary = "创建项目公告") | ||
| 52 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:update')") | ||
| 53 | + public CommonResult<Long> createProjectAnnouncement(@Valid @RequestBody PmsProjectAnnouncementSaveReqVO saveReqVO) { | ||
| 54 | + return success(projectAnnouncementService.createProjectAnnouncement(saveReqVO, getLoginUserId())); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @PutMapping("/update") | ||
| 58 | + @Operation(summary = "更新项目公告") | ||
| 59 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:update')") | ||
| 60 | + public CommonResult<Boolean> updateProjectAnnouncement( | ||
| 61 | + @Valid @RequestBody PmsProjectAnnouncementSaveReqVO saveReqVO) { | ||
| 62 | + projectAnnouncementService.updateProjectAnnouncement(saveReqVO, getLoginUserId()); | ||
| 63 | + return success(true); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + @DeleteMapping("/delete") | ||
| 67 | + @Operation(summary = "删除项目公告") | ||
| 68 | + @Parameter(name = "id", description = "公告编号", required = true, example = "1024") | ||
| 69 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:update')") | ||
| 70 | + public CommonResult<Boolean> deleteProjectAnnouncement(@RequestParam("id") Long id) { | ||
| 71 | + projectAnnouncementService.deleteProjectAnnouncement(id, getLoginUserId()); | ||
| 72 | + return success(true); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + @GetMapping("/get") | ||
| 76 | + @Operation(summary = "获得项目公告详情") | ||
| 77 | + @Parameter(name = "id", description = "公告编号", required = true, example = "1024") | ||
| 78 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:query')") | ||
| 79 | + public CommonResult<PmsProjectAnnouncementRespVO> getProjectAnnouncement(@RequestParam("id") Long id) { | ||
| 80 | + PmsProjectAnnouncementDO announcement = projectAnnouncementService | ||
| 81 | + .getProjectAnnouncement(id, getLoginUserId()); | ||
| 82 | + return success(buildProjectAnnouncementRespVO(announcement)); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + @GetMapping("/list") | ||
| 86 | + @Operation(summary = "获得项目公告列表") | ||
| 87 | + @Parameter(name = "projectId", description = "项目编号", required = true, example = "1024") | ||
| 88 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:query')") | ||
| 89 | + public CommonResult<List<PmsProjectAnnouncementRespVO>> getProjectAnnouncementList( | ||
| 90 | + @RequestParam("projectId") Long projectId) { | ||
| 91 | + List<PmsProjectAnnouncementDO> announcements = projectAnnouncementService | ||
| 92 | + .getProjectAnnouncementList(projectId, getLoginUserId()); | ||
| 93 | + List<PmsProjectAnnouncementRespVO> announcementVOList = buildProjectAnnouncementRespVOList(announcements); | ||
| 94 | + return success(announcementVOList); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + // ==================== 拼接 VO ==================== | ||
| 98 | + | ||
| 99 | + /** | ||
| 100 | + * 构建项目公告响应 | ||
| 101 | + * | ||
| 102 | + * @param announcement 项目公告 | ||
| 103 | + * @return 项目公告响应 | ||
| 104 | + */ | ||
| 105 | + private PmsProjectAnnouncementRespVO buildProjectAnnouncementRespVO(PmsProjectAnnouncementDO announcement) { | ||
| 106 | + return CollUtil.getFirst(buildProjectAnnouncementRespVOList(Collections.singletonList(announcement))); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + /** | ||
| 110 | + * 构建项目公告响应列表 | ||
| 111 | + * | ||
| 112 | + * @param announcements 项目公告列表 | ||
| 113 | + * @return 项目公告响应列表 | ||
| 114 | + */ | ||
| 115 | + private List<PmsProjectAnnouncementRespVO> buildProjectAnnouncementRespVOList( | ||
| 116 | + List<PmsProjectAnnouncementDO> announcements) { | ||
| 117 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(announcements, | ||
| 118 | + announcement -> NumberUtils.parseLong(announcement.getCreator()))); | ||
| 119 | + return convertList(announcements, announcement -> { | ||
| 120 | + PmsProjectAnnouncementRespVO announcementVO = BeanUtils.toBean( | ||
| 121 | + announcement, PmsProjectAnnouncementRespVO.class) | ||
| 122 | + .setCreatorUserId(NumberUtils.parseLong(announcement.getCreator())); | ||
| 123 | + findAndThen(userMap, announcementVO.getCreatorUserId(), | ||
| 124 | + user -> announcementVO.setCreatorUserName(user.getNickname())); | ||
| 125 | + return announcementVO; | ||
| 126 | + }); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/PmsProjectController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 7 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.project.PmsProjectOverviewRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.project.PmsProjectPageReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.project.PmsProjectRespVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.project.PmsProjectSaveReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.project.PmsProjectDO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemStatusTypeEnum; | ||
| 14 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectFavoriteService; | ||
| 15 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectMemberService; | ||
| 16 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectService; | ||
| 17 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemService; | ||
| 18 | +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | ||
| 19 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 20 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 21 | +import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; | ||
| 22 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 23 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 24 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 25 | +import jakarta.annotation.Resource; | ||
| 26 | +import jakarta.validation.Valid; | ||
| 27 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 28 | +import org.springframework.validation.annotation.Validated; | ||
| 29 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 30 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 31 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 32 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 33 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 34 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 35 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 36 | +import org.springframework.web.bind.annotation.RestController; | ||
| 37 | + | ||
| 38 | +import java.util.ArrayList; | ||
| 39 | +import java.util.Collections; | ||
| 40 | +import java.util.List; | ||
| 41 | +import java.util.Map; | ||
| 42 | +import java.util.Set; | ||
| 43 | + | ||
| 44 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 45 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 46 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 47 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 48 | + | ||
| 49 | +@Tag(name = "管理后台 - PMS 项目") | ||
| 50 | +@RestController | ||
| 51 | +@RequestMapping("/pms/pm/project") | ||
| 52 | +@Validated | ||
| 53 | +public class PmsProjectController { | ||
| 54 | + | ||
| 55 | + @Resource | ||
| 56 | + private PmsProjectService projectService; | ||
| 57 | + @Resource | ||
| 58 | + private PmsProjectMemberService projectMemberService; | ||
| 59 | + @Resource | ||
| 60 | + private PmsProjectFavoriteService projectFavoriteService; | ||
| 61 | + @Resource | ||
| 62 | + private PmsWorkItemService workItemService; | ||
| 63 | + @Resource | ||
| 64 | + private AdminUserApi adminUserApi; | ||
| 65 | + @Resource | ||
| 66 | + private PermissionApi permissionApi; | ||
| 67 | + | ||
| 68 | + @PostMapping("/create") | ||
| 69 | + @Operation(summary = "创建项目") | ||
| 70 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:create')") | ||
| 71 | + public CommonResult<Long> createProject(@Valid @RequestBody PmsProjectSaveReqVO saveReqVO) { | ||
| 72 | + return success(projectService.createProject(saveReqVO, getLoginUserId())); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + @PutMapping("/update") | ||
| 76 | + @Operation(summary = "更新项目") | ||
| 77 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:update')") | ||
| 78 | + public CommonResult<Boolean> updateProject(@Valid @RequestBody PmsProjectSaveReqVO saveReqVO) { | ||
| 79 | + projectService.updateProject(saveReqVO, getLoginUserId()); | ||
| 80 | + return success(true); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + @GetMapping("/get") | ||
| 84 | + @Operation(summary = "获得项目详情") | ||
| 85 | + @Parameter(name = "id", description = "项目编号", required = true, example = "1024") | ||
| 86 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:query')") | ||
| 87 | + public CommonResult<PmsProjectRespVO> getProject(@RequestParam("id") Long id) { | ||
| 88 | + Long userId = getLoginUserId(); | ||
| 89 | + PmsProjectDO project = projectService.getProjectAndUpdateVisitTime(id, userId); | ||
| 90 | + return success(buildProjectRespVO(project, userId)); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + @GetMapping("/page") | ||
| 94 | + @Operation(summary = "获得项目分页") | ||
| 95 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:query')") | ||
| 96 | + public CommonResult<PageResult<PmsProjectRespVO>> getProjectPage(@Valid PmsProjectPageReqVO pageReqVO) { | ||
| 97 | + Long userId = getLoginUserId(); | ||
| 98 | + PageResult<PmsProjectDO> pageResult = projectService.getProjectPage(pageReqVO, userId); | ||
| 99 | + return success(new PageResult<>(buildProjectRespVOList(pageResult.getList(), userId), pageResult.getTotal())); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + @GetMapping("/favorite-list") | ||
| 103 | + @Operation(summary = "获得星标项目列表") | ||
| 104 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:query')") | ||
| 105 | + public CommonResult<List<PmsProjectRespVO>> getFavoriteProjectList() { | ||
| 106 | + Long userId = getLoginUserId(); | ||
| 107 | + return success(buildProjectRespVOList(projectService.getFavoriteProjectList(userId), userId)); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + @GetMapping("/overview") | ||
| 111 | + @Operation(summary = "获得项目概况") | ||
| 112 | + @Parameter(name = "projectId", description = "项目编号", required = true, example = "1024") | ||
| 113 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:query')") | ||
| 114 | + public CommonResult<PmsProjectOverviewRespVO> getProjectOverview(@RequestParam("projectId") Long projectId) { | ||
| 115 | + return success(projectService.getProjectOverview(projectId, getLoginUserId())); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + @PutMapping("/archive") | ||
| 119 | + @Operation(summary = "归档项目") | ||
| 120 | + @Parameter(name = "id", description = "项目编号", required = true, example = "1024") | ||
| 121 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:update')") | ||
| 122 | + public CommonResult<Boolean> archiveProject(@RequestParam("id") Long id) { | ||
| 123 | + projectService.archiveProject(id, getLoginUserId()); | ||
| 124 | + return success(true); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + @PutMapping("/recycle") | ||
| 128 | + @Operation(summary = "将项目移入回收站") | ||
| 129 | + @Parameter(name = "id", description = "项目编号", required = true, example = "1024") | ||
| 130 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:update')") | ||
| 131 | + public CommonResult<Boolean> recycleProject(@RequestParam("id") Long id) { | ||
| 132 | + projectService.recycleProject(id, getLoginUserId()); | ||
| 133 | + return success(true); | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + @PutMapping("/restore") | ||
| 137 | + @Operation(summary = "恢复项目") | ||
| 138 | + @Parameter(name = "id", description = "项目编号", required = true, example = "1024") | ||
| 139 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:update')") | ||
| 140 | + public CommonResult<Boolean> restoreProject(@RequestParam("id") Long id) { | ||
| 141 | + projectService.restoreProject(id, getLoginUserId()); | ||
| 142 | + return success(true); | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + @DeleteMapping("/delete") | ||
| 146 | + @Operation(summary = "彻底删除回收站项目") | ||
| 147 | + @Parameter(name = "id", description = "项目编号", required = true, example = "1024") | ||
| 148 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:delete')") | ||
| 149 | + public CommonResult<Boolean> deleteProject(@RequestParam("id") Long id) { | ||
| 150 | + projectService.deleteProject(id, getLoginUserId()); | ||
| 151 | + return success(true); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + // ==================== 拼接 VO ==================== | ||
| 155 | + | ||
| 156 | + private PmsProjectRespVO buildProjectRespVO(PmsProjectDO project, Long userId) { | ||
| 157 | + if (project == null) { | ||
| 158 | + return null; | ||
| 159 | + } | ||
| 160 | + return CollUtil.getFirst(buildProjectRespVOList(Collections.singletonList(project), userId)); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + private List<PmsProjectRespVO> buildProjectRespVOList(List<PmsProjectDO> projects, Long userId) { | ||
| 164 | + if (CollUtil.isEmpty(projects)) { | ||
| 165 | + return Collections.emptyList(); | ||
| 166 | + } | ||
| 167 | + // 1. 批量查询创建人、项目管理员、成员数量和工作项完成度 | ||
| 168 | + Set<Long> projectIds = convertSet(projects, PmsProjectDO::getId); | ||
| 169 | + Map<Long, List<Long>> managerUserIdListMap = projectMemberService.getProjectManagerUserIdListMap(projectIds); | ||
| 170 | + Map<Long, Integer> memberCountMap = projectMemberService.getProjectMemberCountMap(projectIds); | ||
| 171 | + Map<Long, Map<Integer, Long>> projectStatusCountMap = workItemService | ||
| 172 | + .getProjectWorkItemStatusCountMap(projectIds); | ||
| 173 | + Set<Long> userIds = convertSet(projects, project -> | ||
| 174 | + NumberUtils.parseLong(project.getCreator())); | ||
| 175 | + managerUserIdListMap.values().forEach(userIds::addAll); | ||
| 176 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||
| 177 | + Set<Long> ownerProjectIds = convertSet(projectMemberService.getOwnerProjectIdListByUserId(userId)); | ||
| 178 | + Set<Long> managedProjectIds = convertSet(projectMemberService.getManagedProjectIdListByUserId(userId)); | ||
| 179 | + Set<Long> memberProjectIds = convertSet(projectMemberService.getProjectIdListByUserId(userId)); | ||
| 180 | + Set<Long> writableProjectIds = convertSet(projectMemberService.getWritableProjectIdListByUserId(userId)); | ||
| 181 | + Set<Long> favoriteProjectIds = convertSet(projectFavoriteService.getFavoriteProjectIdListByUserId(userId)); | ||
| 182 | + favoriteProjectIds.retainAll(projectIds); | ||
| 183 | + boolean superAdmin = permissionApi.hasAnyRoles(userId, RoleCodeEnum.SUPER_ADMIN.getCode()); | ||
| 184 | + // 2. 转换项目响应,并拼接展示字段 | ||
| 185 | + return BeanUtils.toBean(projects, PmsProjectRespVO.class, projectVO -> { | ||
| 186 | + findAndThen(userMap, NumberUtils.parseLong(projectVO.getCreator()), | ||
| 187 | + creator -> projectVO.setCreatorName(creator.getNickname())); | ||
| 188 | + List<String> adminNames = new ArrayList<>(); | ||
| 189 | + for (Long adminUserId : managerUserIdListMap.getOrDefault(projectVO.getId(), Collections.emptyList())) { | ||
| 190 | + findAndThen(userMap, adminUserId, admin -> adminNames.add(admin.getNickname())); | ||
| 191 | + } | ||
| 192 | + Map<Integer, Long> statusCountMap = projectStatusCountMap.getOrDefault( | ||
| 193 | + projectVO.getId(), Collections.emptyMap()); | ||
| 194 | + projectVO.setAdminNames(adminNames).setMemberCount(memberCountMap.getOrDefault(projectVO.getId(), 0)) | ||
| 195 | + .setPendingWorkItemCount(statusCountMap.getOrDefault(PmsWorkItemStatusTypeEnum.PENDING.getType(), 0L)) | ||
| 196 | + .setProcessingWorkItemCount(statusCountMap.getOrDefault(PmsWorkItemStatusTypeEnum.PROCESSING.getType(), 0L)) | ||
| 197 | + .setCompletedWorkItemCount(statusCountMap.getOrDefault(PmsWorkItemStatusTypeEnum.COMPLETED.getType(), 0L)) | ||
| 198 | + .setOwnerStatus(superAdmin || ownerProjectIds.contains(projectVO.getId())) | ||
| 199 | + .setAdminStatus(superAdmin || managedProjectIds.contains(projectVO.getId())) | ||
| 200 | + .setMemberStatus(memberProjectIds.contains(projectVO.getId())) | ||
| 201 | + .setExitStatus(memberProjectIds.contains(projectVO.getId()) && !ownerProjectIds.contains(projectVO.getId())) | ||
| 202 | + .setWriteStatus(superAdmin || writableProjectIds.contains(projectVO.getId())) | ||
| 203 | + .setFavoriteStatus(favoriteProjectIds.contains(projectVO.getId())); | ||
| 204 | + }); | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/PmsProjectFavoriteController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectFavoriteService; | ||
| 5 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 6 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 7 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 8 | +import jakarta.annotation.Resource; | ||
| 9 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 10 | +import org.springframework.validation.annotation.Validated; | ||
| 11 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 12 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 13 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 14 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 15 | +import org.springframework.web.bind.annotation.RestController; | ||
| 16 | + | ||
| 17 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 18 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 19 | + | ||
| 20 | +@Tag(name = "管理后台 - PMS 项目收藏") | ||
| 21 | +@RestController | ||
| 22 | +@RequestMapping("/pms/pm/project-favorite") | ||
| 23 | +@Validated | ||
| 24 | +public class PmsProjectFavoriteController { | ||
| 25 | + | ||
| 26 | + @Resource | ||
| 27 | + private PmsProjectFavoriteService projectFavoriteService; | ||
| 28 | + | ||
| 29 | + @PostMapping("/create") | ||
| 30 | + @Operation(summary = "收藏项目") | ||
| 31 | + @Parameter(name = "projectId", description = "项目编号", required = true, example = "1024") | ||
| 32 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:query')") | ||
| 33 | + public CommonResult<Boolean> createProjectFavorite(@RequestParam("projectId") Long projectId) { | ||
| 34 | + projectFavoriteService.createProjectFavorite(projectId, getLoginUserId()); | ||
| 35 | + return success(true); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @DeleteMapping("/delete") | ||
| 39 | + @Operation(summary = "取消收藏项目") | ||
| 40 | + @Parameter(name = "projectId", description = "项目编号", required = true, example = "1024") | ||
| 41 | + @PreAuthorize("@ss.hasPermission('pms:pm:project:query')") | ||
| 42 | + public CommonResult<Boolean> deleteProjectFavorite(@RequestParam("projectId") Long projectId) { | ||
| 43 | + projectFavoriteService.deleteProjectFavorite(projectId, getLoginUserId()); | ||
| 44 | + return success(true); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/PmsProjectGroupController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.group.PmsProjectGroupMoveReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.group.PmsProjectGroupRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.group.PmsProjectGroupSaveReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.group.PmsProjectGroupSortReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.project.PmsProjectGroupDO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectGroupService; | ||
| 11 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectMemberService; | ||
| 12 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 13 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 14 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 15 | +import jakarta.annotation.Resource; | ||
| 16 | +import jakarta.validation.Valid; | ||
| 17 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 18 | +import org.springframework.validation.annotation.Validated; | ||
| 19 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 23 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 25 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 26 | +import org.springframework.web.bind.annotation.RestController; | ||
| 27 | + | ||
| 28 | +import java.util.List; | ||
| 29 | +import java.util.Map; | ||
| 30 | + | ||
| 31 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 32 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 33 | + | ||
| 34 | +@Tag(name = "管理后台 - PMS 项目分组") | ||
| 35 | +@RestController | ||
| 36 | +@RequestMapping("/pms/pm/project-group") | ||
| 37 | +@Validated | ||
| 38 | +public class PmsProjectGroupController { | ||
| 39 | + | ||
| 40 | + @Resource | ||
| 41 | + private PmsProjectGroupService projectGroupService; | ||
| 42 | + @Resource | ||
| 43 | + private PmsProjectMemberService projectMemberService; | ||
| 44 | + | ||
| 45 | + @PostMapping("/create") | ||
| 46 | + @Operation(summary = "创建项目分组") | ||
| 47 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-group:create')") | ||
| 48 | + public CommonResult<Long> createProjectGroup(@Valid @RequestBody PmsProjectGroupSaveReqVO createReqVO) { | ||
| 49 | + return success(projectGroupService.createProjectGroup(createReqVO, getLoginUserId())); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @PutMapping("/update") | ||
| 53 | + @Operation(summary = "修改项目分组") | ||
| 54 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-group:update')") | ||
| 55 | + public CommonResult<Boolean> updateProjectGroup(@Valid @RequestBody PmsProjectGroupSaveReqVO updateReqVO) { | ||
| 56 | + projectGroupService.updateProjectGroup(updateReqVO, getLoginUserId()); | ||
| 57 | + return success(true); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + @PutMapping("/update-sort") | ||
| 61 | + @Operation(summary = "修改项目分组排序") | ||
| 62 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-group:update')") | ||
| 63 | + public CommonResult<Boolean> updateProjectGroupSort(@Valid @RequestBody PmsProjectGroupSortReqVO sortReqVO) { | ||
| 64 | + projectGroupService.updateProjectGroupSort(sortReqVO, getLoginUserId()); | ||
| 65 | + return success(true); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + @DeleteMapping("/delete") | ||
| 69 | + @Operation(summary = "删除项目分组") | ||
| 70 | + @Parameter(name = "id", description = "项目分组编号", required = true, example = "1024") | ||
| 71 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-group:delete')") | ||
| 72 | + public CommonResult<Boolean> deleteProjectGroup(@RequestParam("id") Long id) { | ||
| 73 | + projectGroupService.deleteProjectGroup(id, getLoginUserId()); | ||
| 74 | + return success(true); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @GetMapping("/list") | ||
| 78 | + @Operation(summary = "获得项目分组列表") | ||
| 79 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-group:query')") | ||
| 80 | + public CommonResult<List<PmsProjectGroupRespVO>> getProjectGroupList() { | ||
| 81 | + Long userId = getLoginUserId(); | ||
| 82 | + List<PmsProjectGroupDO> groups = projectGroupService.getProjectGroupList(userId); | ||
| 83 | + List<Long> projectIds = projectMemberService.getActiveProjectIdListByUserId(userId); | ||
| 84 | + Map<Long, Integer> groupCountMap = projectGroupService.getProjectGroupCountMap(userId, groups, projectIds); | ||
| 85 | + return success(BeanUtils.toBean(groups, PmsProjectGroupRespVO.class, | ||
| 86 | + group -> group.setProjectCount(groupCountMap.getOrDefault(group.getId(), 0)))); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + @PutMapping("/move-project") | ||
| 90 | + @Operation(summary = "移动项目到个人分组") | ||
| 91 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-group:update')") | ||
| 92 | + public CommonResult<Boolean> moveProjectToGroup(@Valid @RequestBody PmsProjectGroupMoveReqVO moveReqVO) { | ||
| 93 | + projectGroupService.moveProjectToGroup(moveReqVO, getLoginUserId()); | ||
| 94 | + return success(true); | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/PmsProjectMemberController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.member.PmsProjectMemberRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.member.PmsProjectMemberSaveReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectMemberService; | ||
| 9 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 10 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 11 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 12 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 13 | +import io.swagger.v3.oas.annotations.Parameters; | ||
| 14 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 15 | +import jakarta.annotation.Resource; | ||
| 16 | +import jakarta.validation.Valid; | ||
| 17 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 18 | +import org.springframework.validation.annotation.Validated; | ||
| 19 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 23 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 25 | +import org.springframework.web.bind.annotation.RestController; | ||
| 26 | + | ||
| 27 | +import java.util.Collections; | ||
| 28 | +import java.util.List; | ||
| 29 | +import java.util.Map; | ||
| 30 | + | ||
| 31 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 32 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 33 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 34 | + | ||
| 35 | +@Tag(name = "管理后台 - PMS 项目成员") | ||
| 36 | +@RestController | ||
| 37 | +@RequestMapping("/pms/pm/project-member") | ||
| 38 | +@Validated | ||
| 39 | +public class PmsProjectMemberController { | ||
| 40 | + | ||
| 41 | + @Resource | ||
| 42 | + private PmsProjectMemberService projectMemberService; | ||
| 43 | + | ||
| 44 | + @Resource | ||
| 45 | + private AdminUserApi adminUserApi; | ||
| 46 | + | ||
| 47 | + @GetMapping("/list") | ||
| 48 | + @Operation(summary = "获得项目成员列表") | ||
| 49 | + @Parameter(name = "projectId", description = "项目编号", required = true, example = "1024") | ||
| 50 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-member:query')") | ||
| 51 | + public CommonResult<List<PmsProjectMemberRespVO>> getProjectMemberList( | ||
| 52 | + @RequestParam("projectId") Long projectId) { | ||
| 53 | + List<PmsProjectMemberRespVO> members = projectMemberService.getProjectMemberList(projectId, getLoginUserId()); | ||
| 54 | + return success(fillProjectMemberRespVOList(members)); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @PutMapping("/update-list") | ||
| 58 | + @Operation(summary = "保存项目成员及其权限级别") | ||
| 59 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-member:update')") | ||
| 60 | + public CommonResult<Boolean> updateProjectMemberList(@Valid @RequestBody PmsProjectMemberSaveReqVO saveReqVO) { | ||
| 61 | + projectMemberService.updateProjectMemberList(saveReqVO, getLoginUserId()); | ||
| 62 | + return success(true); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @DeleteMapping("/delete") | ||
| 66 | + @Operation(summary = "移除项目成员") | ||
| 67 | + @Parameters({ | ||
| 68 | + @Parameter(name = "projectId", description = "项目编号", required = true, example = "1024"), | ||
| 69 | + @Parameter(name = "userId", description = "后台用户编号", required = true, example = "1") | ||
| 70 | + }) | ||
| 71 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-member:update')") | ||
| 72 | + public CommonResult<Boolean> deleteProjectMember(@RequestParam("projectId") Long projectId, | ||
| 73 | + @RequestParam("userId") Long userId) { | ||
| 74 | + projectMemberService.deleteProjectMember(projectId, userId, getLoginUserId()); | ||
| 75 | + return success(true); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + @DeleteMapping("/exit") | ||
| 79 | + @Operation(summary = "主动退出项目") | ||
| 80 | + @Parameter(name = "projectId", description = "项目编号", required = true, example = "1024") | ||
| 81 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-member:query')") | ||
| 82 | + public CommonResult<Boolean> exitProject(@RequestParam("projectId") Long projectId) { | ||
| 83 | + projectMemberService.exitProject(projectId, getLoginUserId()); | ||
| 84 | + return success(true); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + // ==================== 拼接 VO ==================== | ||
| 88 | + | ||
| 89 | + private List<PmsProjectMemberRespVO> fillProjectMemberRespVOList(List<PmsProjectMemberRespVO> members) { | ||
| 90 | + if (CollUtil.isEmpty(members)) { | ||
| 91 | + return Collections.emptyList(); | ||
| 92 | + } | ||
| 93 | + // 1. 批量查询用户 | ||
| 94 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||
| 95 | + convertSet(members, PmsProjectMemberRespVO::getUserId)); | ||
| 96 | + // 2. 拼接用户信息 | ||
| 97 | + for (PmsProjectMemberRespVO memberVO : members) { | ||
| 98 | + MapUtils.findAndThen(userMap, memberVO.getUserId(), | ||
| 99 | + user -> memberVO.setNickname(user.getNickname()).setAvatar(user.getAvatar())); | ||
| 100 | + } | ||
| 101 | + return members; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/PmsProjectTemplateController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.template.PmsProjectTemplatePageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.template.PmsProjectTemplateRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.template.PmsProjectTemplateSaveReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.project.PmsProjectTemplateDO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectTemplateService; | ||
| 11 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 12 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 13 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 14 | +import jakarta.annotation.Resource; | ||
| 15 | +import jakarta.validation.Valid; | ||
| 16 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 17 | +import org.springframework.validation.annotation.Validated; | ||
| 18 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 23 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 25 | +import org.springframework.web.bind.annotation.RestController; | ||
| 26 | + | ||
| 27 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 28 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 29 | + | ||
| 30 | +@Tag(name = "管理后台 - PMS 项目模板") | ||
| 31 | +@RestController | ||
| 32 | +@RequestMapping("/pms/pm/project-template") | ||
| 33 | +@Validated | ||
| 34 | +public class PmsProjectTemplateController { | ||
| 35 | + | ||
| 36 | + @Resource | ||
| 37 | + private PmsProjectTemplateService projectTemplateService; | ||
| 38 | + | ||
| 39 | + @PostMapping("/create") | ||
| 40 | + @Operation(summary = "创建项目模板") | ||
| 41 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-template:create')") | ||
| 42 | + public CommonResult<Long> createProjectTemplate(@Valid @RequestBody PmsProjectTemplateSaveReqVO createReqVO) { | ||
| 43 | + return success(projectTemplateService.createProjectTemplate(createReqVO)); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + @PutMapping("/update") | ||
| 47 | + @Operation(summary = "更新项目模板") | ||
| 48 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-template:update')") | ||
| 49 | + public CommonResult<Boolean> updateProjectTemplate(@Valid @RequestBody PmsProjectTemplateSaveReqVO updateReqVO) { | ||
| 50 | + projectTemplateService.updateProjectTemplate(updateReqVO); | ||
| 51 | + return success(true); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + @DeleteMapping("/delete") | ||
| 55 | + @Operation(summary = "删除项目模板") | ||
| 56 | + @Parameter(name = "id", description = "模板编号", required = true, example = "1024") | ||
| 57 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-template:delete')") | ||
| 58 | + public CommonResult<Boolean> deleteProjectTemplate(@RequestParam("id") Long id) { | ||
| 59 | + projectTemplateService.deleteProjectTemplate(id); | ||
| 60 | + return success(true); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + @GetMapping("/get") | ||
| 64 | + @Operation(summary = "获得项目模板") | ||
| 65 | + @Parameter(name = "id", description = "模板编号", required = true, example = "1024") | ||
| 66 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-template:query')") | ||
| 67 | + public CommonResult<PmsProjectTemplateRespVO> getProjectTemplate(@RequestParam("id") Long id) { | ||
| 68 | + PmsProjectTemplateDO template = projectTemplateService.getProjectTemplate(id); | ||
| 69 | + return success(BeanUtils.toBean(template, PmsProjectTemplateRespVO.class)); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + @GetMapping("/page") | ||
| 73 | + @Operation(summary = "获得项目模板分页") | ||
| 74 | + @PreAuthorize("@ss.hasPermission('pms:pm:project-template:query')") | ||
| 75 | + public CommonResult<PageResult<PmsProjectTemplateRespVO>> getProjectTemplatePage( | ||
| 76 | + @Valid PmsProjectTemplatePageReqVO pageReqVO) { | ||
| 77 | + PageResult<PmsProjectTemplateDO> pageResult = projectTemplateService.getProjectTemplatePage(pageReqVO); | ||
| 78 | + return success(BeanUtils.toBean(pageResult, PmsProjectTemplateRespVO.class)); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/announcement/PmsProjectAnnouncementRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.announcement; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 项目公告 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsProjectAnnouncementRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "公告编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | ||
| 17 | + private Long projectId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "公告内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "项目启动") | ||
| 20 | + private String content; | ||
| 21 | + | ||
| 22 | + @Schema(description = "附件地址列表", example = "[\"https://example.com/a.pdf\"]") | ||
| 23 | + private List<String> fileUrls; | ||
| 24 | + | ||
| 25 | + @Schema(description = "创建者用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 26 | + private Long creatorUserId; | ||
| 27 | + | ||
| 28 | + @Schema(description = "创建者用户昵称", example = "芋道") | ||
| 29 | + private String creatorUserName; | ||
| 30 | + | ||
| 31 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 32 | + private LocalDateTime createTime; | ||
| 33 | + | ||
| 34 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 35 | + private LocalDateTime updateTime; | ||
| 36 | + | ||
| 37 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/announcement/PmsProjectAnnouncementSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.announcement; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 6 | +import jakarta.validation.constraints.Size; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +@Schema(description = "管理后台 - PMS 项目公告保存 Request VO") | ||
| 12 | +@Data | ||
| 13 | +public class PmsProjectAnnouncementSaveReqVO { | ||
| 14 | + | ||
| 15 | + @Schema(description = "公告编号", example = "1024") | ||
| 16 | + private Long id; | ||
| 17 | + | ||
| 18 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 19 | + @NotNull(message = "项目编号不能为空") | ||
| 20 | + private Long projectId; | ||
| 21 | + | ||
| 22 | + @Schema(description = "公告内容", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 23 | + @NotBlank(message = "公告内容不能为空") | ||
| 24 | + @Size(max = 5000, message = "公告内容不能超过 5000 个字符") | ||
| 25 | + private String content; | ||
| 26 | + | ||
| 27 | + @Schema(description = "附件地址列表") | ||
| 28 | + private List<String> fileUrls; | ||
| 29 | + | ||
| 30 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/group/PmsProjectGroupMoveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.group; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - PMS 项目移动分组 Request VO") | ||
| 8 | +@Data | ||
| 9 | +public class PmsProjectGroupMoveReqVO { | ||
| 10 | + | ||
| 11 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 12 | + @NotNull(message = "项目编号不能为空") | ||
| 13 | + private Long projectId; | ||
| 14 | + | ||
| 15 | + @Schema(description = "目标项目分组编号;不传表示移动到未分组", example = "2048") | ||
| 16 | + private Long groupId; | ||
| 17 | + | ||
| 18 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/group/PmsProjectGroupRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.group; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 项目分组 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsProjectGroupRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "项目分组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "分组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "重点项目") | ||
| 16 | + private String name; | ||
| 17 | + | ||
| 18 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 19 | + private Integer sort; | ||
| 20 | + | ||
| 21 | + @Schema(description = "分组类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 22 | + private Integer type; | ||
| 23 | + | ||
| 24 | + @Schema(description = "创建时间") | ||
| 25 | + private LocalDateTime createTime; | ||
| 26 | + | ||
| 27 | + @Schema(description = "项目数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") | ||
| 28 | + private Integer projectCount; | ||
| 29 | + | ||
| 30 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/group/PmsProjectGroupSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.group; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.Size; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 项目分组新增/修改 Request VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsProjectGroupSaveReqVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "项目分组编号", example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "分组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "重点项目") | ||
| 16 | + @NotBlank(message = "分组名称不能为空") | ||
| 17 | + @Size(max = 100, message = "分组名称不能超过 100 个字符") | ||
| 18 | + private String name; | ||
| 19 | + | ||
| 20 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/group/PmsProjectGroupSortReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.group; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.Valid; | ||
| 5 | +import jakarta.validation.constraints.Min; | ||
| 6 | +import jakarta.validation.constraints.NotEmpty; | ||
| 7 | +import jakarta.validation.constraints.NotNull; | ||
| 8 | +import lombok.Data; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +@Schema(description = "管理后台 - PMS 项目分组排序 Request VO") | ||
| 13 | +@Data | ||
| 14 | +public class PmsProjectGroupSortReqVO { | ||
| 15 | + | ||
| 16 | + @Schema(description = "项目分组排序项", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 17 | + @Valid | ||
| 18 | + @NotEmpty(message = "项目分组排序项不能为空") | ||
| 19 | + private List<Item> items; | ||
| 20 | + | ||
| 21 | + @Schema(description = "管理后台 - PMS 项目分组排序项") | ||
| 22 | + @Data | ||
| 23 | + public static class Item { | ||
| 24 | + | ||
| 25 | + @Schema(description = "项目分组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 26 | + @NotNull(message = "项目分组编号不能为空") | ||
| 27 | + private Long id; | ||
| 28 | + | ||
| 29 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 30 | + @NotNull(message = "显示顺序不能为空") | ||
| 31 | + @Min(value = 0, message = "显示顺序不能小于 0") | ||
| 32 | + private Integer sort; | ||
| 33 | + | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/member/PmsProjectMemberRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.member; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +@Schema(description = "管理后台 - PMS 项目成员 Response VO") | ||
| 7 | +@Data | ||
| 8 | +public class PmsProjectMemberRespVO { | ||
| 9 | + | ||
| 10 | + @Schema(description = "后台用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 11 | + private Long userId; | ||
| 12 | + | ||
| 13 | + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") | ||
| 14 | + private String nickname; | ||
| 15 | + | ||
| 16 | + @Schema(description = "用户头像") | ||
| 17 | + private String avatar; | ||
| 18 | + | ||
| 19 | + @Schema(description = "成员权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 20 | + private Integer level; | ||
| 21 | + | ||
| 22 | + @Schema(description = "是否项目创建人", example = "true") | ||
| 23 | + private Boolean creatorStatus; | ||
| 24 | + | ||
| 25 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/member/PmsProjectMemberSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.member; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 4 | +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectMemberLevelEnum; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import jakarta.validation.Valid; | ||
| 7 | +import jakarta.validation.constraints.NotEmpty; | ||
| 8 | +import jakarta.validation.constraints.NotNull; | ||
| 9 | +import lombok.Data; | ||
| 10 | + | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 13 | +@Schema(description = "管理后台 - PMS 项目成员保存 Request VO") | ||
| 14 | +@Data | ||
| 15 | +public class PmsProjectMemberSaveReqVO { | ||
| 16 | + | ||
| 17 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 18 | + @NotNull(message = "项目编号不能为空") | ||
| 19 | + private Long projectId; | ||
| 20 | + | ||
| 21 | + @Schema(description = "项目成员列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 22 | + @NotEmpty(message = "项目成员不能为空") | ||
| 23 | + @Valid | ||
| 24 | + private List<Member> members; | ||
| 25 | + | ||
| 26 | + @Schema(description = "管理后台 - PMS 项目成员保存项") | ||
| 27 | + @Data | ||
| 28 | + public static class Member { | ||
| 29 | + | ||
| 30 | + @Schema(description = "后台用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 31 | + @NotNull(message = "后台用户编号不能为空") | ||
| 32 | + private Long userId; | ||
| 33 | + | ||
| 34 | + @Schema(description = "成员权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 35 | + @NotNull(message = "成员权限级别不能为空") | ||
| 36 | + @InEnum(PmsProjectMemberLevelEnum.class) | ||
| 37 | + private Integer level; | ||
| 38 | + | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/project/PmsProjectOverviewRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.project; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | +import java.util.Map; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - PMS 项目概况 Response VO") | ||
| 11 | +@Data | ||
| 12 | +public class PmsProjectOverviewRespVO { | ||
| 13 | + | ||
| 14 | + @Schema(description = "工作项总数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") | ||
| 15 | + private Long totalCount; | ||
| 16 | + | ||
| 17 | + @Schema(description = "未开始工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8") | ||
| 18 | + private Long pendingCount; | ||
| 19 | + | ||
| 20 | + @Schema(description = "进行中工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "6") | ||
| 21 | + private Long processingCount; | ||
| 22 | + | ||
| 23 | + @Schema(description = "已完成工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "6") | ||
| 24 | + private Long completedCount; | ||
| 25 | + | ||
| 26 | + @Schema(description = "按工作项类型统计") | ||
| 27 | + private Map<Integer, Long> typeCountMap; | ||
| 28 | + | ||
| 29 | + @Schema(description = "近十四日完成趋势") | ||
| 30 | + private List<TrendPoint> completedTrends; | ||
| 31 | + | ||
| 32 | + @Schema(description = "分配给当前用户的未完成工作项") | ||
| 33 | + private List<AssignedWorkItem> assignedWorkItems; | ||
| 34 | + | ||
| 35 | + @Schema(description = "PMS 项目概况 - 趋势点") | ||
| 36 | + @Data | ||
| 37 | + public static class TrendPoint { | ||
| 38 | + | ||
| 39 | + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 40 | + private String date; | ||
| 41 | + | ||
| 42 | + @Schema(description = "当日完成数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 43 | + private Long count; | ||
| 44 | + | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @Schema(description = "PMS 项目概况 - 分配给我的工作项") | ||
| 48 | + @Data | ||
| 49 | + public static class AssignedWorkItem { | ||
| 50 | + | ||
| 51 | + @Schema(description = "工作项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 52 | + private Long id; | ||
| 53 | + | ||
| 54 | + @Schema(description = "项目内序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12") | ||
| 55 | + private Integer serialNumber; | ||
| 56 | + | ||
| 57 | + @Schema(description = "工作项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 58 | + private Integer type; | ||
| 59 | + | ||
| 60 | + @Schema(description = "工作项标题", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 61 | + private String name; | ||
| 62 | + | ||
| 63 | + @Schema(description = "语义状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 64 | + private Integer status; | ||
| 65 | + | ||
| 66 | + @Schema(description = "截止时间") | ||
| 67 | + private LocalDateTime endTime; | ||
| 68 | + | ||
| 69 | + @Schema(description = "完成进度", requiredMode = Schema.RequiredMode.REQUIRED, example = "60") | ||
| 70 | + private Integer progress; | ||
| 71 | + | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/project/PmsProjectPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.project; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectSceneTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectSortTypeEnum; | ||
| 7 | +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectStatusEnum; | ||
| 8 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 9 | +import lombok.Data; | ||
| 10 | +import lombok.EqualsAndHashCode; | ||
| 11 | +import lombok.ToString; | ||
| 12 | + | ||
| 13 | +@Schema(description = "管理后台 - PMS 项目分页 Request VO") | ||
| 14 | +@Data | ||
| 15 | +@EqualsAndHashCode(callSuper = true) | ||
| 16 | +@ToString(callSuper = true) | ||
| 17 | +public class PmsProjectPageReqVO extends PageParam { | ||
| 18 | + | ||
| 19 | + @Schema(description = "项目名称", example = "官网") | ||
| 20 | + private String name; | ||
| 21 | + | ||
| 22 | + @Schema(description = "列表场景", example = "1") | ||
| 23 | + @InEnum(PmsProjectSceneTypeEnum.class) | ||
| 24 | + private Integer sceneType = PmsProjectSceneTypeEnum.ALL.getType(); | ||
| 25 | + | ||
| 26 | + @Schema(description = "个人项目分组编号", example = "1024") | ||
| 27 | + private Long groupId; | ||
| 28 | + | ||
| 29 | + @Schema(description = "项目状态", example = "1") | ||
| 30 | + @InEnum(PmsProjectStatusEnum.class) | ||
| 31 | + private Integer status = PmsProjectStatusEnum.ACTIVE.getStatus(); | ||
| 32 | + | ||
| 33 | + @Schema(description = "排序类型", example = "1") | ||
| 34 | + @InEnum(PmsProjectSortTypeEnum.class) | ||
| 35 | + private Integer sortType = PmsProjectSortTypeEnum.ACCESS_TIME.getType(); | ||
| 36 | + | ||
| 37 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/project/PmsProjectRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.project; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 项目 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsProjectRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "官网重构") | ||
| 17 | + private String name; | ||
| 18 | + | ||
| 19 | + @Schema(description = "项目状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 20 | + private Integer status; | ||
| 21 | + | ||
| 22 | + @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 23 | + private Integer type; | ||
| 24 | + | ||
| 25 | + @Schema(description = "项目优先级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 26 | + private Integer level; | ||
| 27 | + | ||
| 28 | + @Schema(description = "项目描述", example = "完成官网前后端重构") | ||
| 29 | + private String description; | ||
| 30 | + | ||
| 31 | + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 32 | + private Boolean openStatus; | ||
| 33 | + | ||
| 34 | + @Schema(description = "项目图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "ep:folder") | ||
| 35 | + private String icon; | ||
| 36 | + | ||
| 37 | + @Schema(description = "开始时间") | ||
| 38 | + private LocalDateTime startTime; | ||
| 39 | + | ||
| 40 | + @Schema(description = "截止时间") | ||
| 41 | + private LocalDateTime endTime; | ||
| 42 | + | ||
| 43 | + @Schema(description = "归档时间") | ||
| 44 | + private LocalDateTime archiveTime; | ||
| 45 | + | ||
| 46 | + @Schema(description = "移入回收站时间") | ||
| 47 | + private LocalDateTime recycleTime; | ||
| 48 | + | ||
| 49 | + @Schema(description = "最近访问时间") | ||
| 50 | + private LocalDateTime accessTime; | ||
| 51 | + | ||
| 52 | + @Schema(description = "创建时间") | ||
| 53 | + private LocalDateTime createTime; | ||
| 54 | + | ||
| 55 | + @Schema(description = "创建人编号", example = "1") | ||
| 56 | + private String creator; | ||
| 57 | + | ||
| 58 | + @Schema(description = "创建人姓名", example = "芋道源码") | ||
| 59 | + private String creatorName; | ||
| 60 | + | ||
| 61 | + @Schema(description = "项目管理员姓名列表") | ||
| 62 | + private List<String> adminNames; | ||
| 63 | + | ||
| 64 | + @Schema(description = "项目成员数量", example = "5") | ||
| 65 | + private Integer memberCount; | ||
| 66 | + | ||
| 67 | + @Schema(description = "未开始工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 68 | + private Long pendingWorkItemCount; | ||
| 69 | + | ||
| 70 | + @Schema(description = "进行中工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 71 | + private Long processingWorkItemCount; | ||
| 72 | + | ||
| 73 | + @Schema(description = "已完成工作项数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") | ||
| 74 | + private Long completedWorkItemCount; | ||
| 75 | + | ||
| 76 | + @Schema(description = "当前用户是否为项目管理员", example = "true") | ||
| 77 | + private Boolean adminStatus; | ||
| 78 | + | ||
| 79 | + @Schema(description = "当前用户是否拥有项目所有者权限", example = "true") | ||
| 80 | + private Boolean ownerStatus; | ||
| 81 | + | ||
| 82 | + @Schema(description = "当前用户是否为项目成员", example = "true") | ||
| 83 | + private Boolean memberStatus; | ||
| 84 | + | ||
| 85 | + @Schema(description = "当前用户是否可以主动退出项目", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 86 | + private Boolean exitStatus; | ||
| 87 | + | ||
| 88 | + @Schema(description = "当前用户是否可以编辑项目业务数据", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 89 | + private Boolean writeStatus; | ||
| 90 | + | ||
| 91 | + @Schema(description = "当前用户是否已收藏", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 92 | + private Boolean favoriteStatus; | ||
| 93 | + | ||
| 94 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/project/PmsProjectSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.project; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 4 | +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectLevelEnum; | ||
| 5 | +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectTypeEnum; | ||
| 6 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
| 7 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 8 | +import jakarta.validation.constraints.AssertTrue; | ||
| 9 | +import jakarta.validation.constraints.NotBlank; | ||
| 10 | +import jakarta.validation.constraints.NotNull; | ||
| 11 | +import jakarta.validation.constraints.Size; | ||
| 12 | +import lombok.Data; | ||
| 13 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 14 | + | ||
| 15 | +import java.time.LocalDateTime; | ||
| 16 | +import java.util.List; | ||
| 17 | + | ||
| 18 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 19 | + | ||
| 20 | +@Schema(description = "管理后台 - PMS 项目新增/修改 Request VO") | ||
| 21 | +@Data | ||
| 22 | +public class PmsProjectSaveReqVO { | ||
| 23 | + | ||
| 24 | + @Schema(description = "项目编号", example = "1024") | ||
| 25 | + private Long id; | ||
| 26 | + | ||
| 27 | + @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "官网重构") | ||
| 28 | + @NotBlank(message = "项目名称不能为空") | ||
| 29 | + @Size(max = 31, message = "项目名称不能超过 31 个字符") | ||
| 30 | + private String name; | ||
| 31 | + | ||
| 32 | + @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 33 | + @NotNull(message = "项目类型不能为空") | ||
| 34 | + @InEnum(PmsProjectTypeEnum.class) | ||
| 35 | + private Integer type; | ||
| 36 | + | ||
| 37 | + @Schema(description = "项目优先级", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 38 | + @NotNull(message = "项目优先级不能为空") | ||
| 39 | + @InEnum(PmsProjectLevelEnum.class) | ||
| 40 | + private Integer level; | ||
| 41 | + | ||
| 42 | + @Schema(description = "项目描述", example = "完成官网前后端重构") | ||
| 43 | + @Size(max = 500, message = "项目描述不能超过 500 个字符") | ||
| 44 | + private String description; | ||
| 45 | + | ||
| 46 | + @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 47 | + @NotNull(message = "项目可见范围不能为空") | ||
| 48 | + private Boolean openStatus; | ||
| 49 | + | ||
| 50 | + @Schema(description = "项目图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "ep:folder") | ||
| 51 | + @NotBlank(message = "项目图标不能为空") | ||
| 52 | + private String icon; | ||
| 53 | + | ||
| 54 | + @Schema(description = "开始时间", example = "2026-08-01 00:00:00") | ||
| 55 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 56 | + private LocalDateTime startTime; | ||
| 57 | + | ||
| 58 | + @Schema(description = "截止时间", example = "2026-12-31 23:59:59") | ||
| 59 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 60 | + private LocalDateTime endTime; | ||
| 61 | + | ||
| 62 | + @Schema(description = "初始成员编号列表", example = "[1, 2]") | ||
| 63 | + private List<Long> memberUserIds; | ||
| 64 | + | ||
| 65 | + @JsonIgnore | ||
| 66 | + @Schema(hidden = true) | ||
| 67 | + @AssertTrue(message = "项目截止时间必须晚于开始时间,且开始、截止时间需要同时填写") | ||
| 68 | + public boolean isTimeValid() { | ||
| 69 | + return startTime == null && endTime == null | ||
| 70 | + || startTime != null && endTime != null && startTime.isBefore(endTime); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/template/PmsProjectTemplatePageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.template; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectTypeEnum; | ||
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | + | ||
| 10 | +@Schema(description = "管理后台 - PMS 项目模板分页 Request VO") | ||
| 11 | +@Data | ||
| 12 | +@EqualsAndHashCode(callSuper = true) | ||
| 13 | +public class PmsProjectTemplatePageReqVO extends PageParam { | ||
| 14 | + | ||
| 15 | + @Schema(description = "模板名称,模糊匹配", example = "敏捷研发模板") | ||
| 16 | + private String name; | ||
| 17 | + | ||
| 18 | + @Schema(description = "项目类型", example = "2") | ||
| 19 | + @InEnum(PmsProjectTypeEnum.class) | ||
| 20 | + private Integer projectType; | ||
| 21 | + | ||
| 22 | + @Schema(description = "模板状态", example = "0") | ||
| 23 | + private Integer status; | ||
| 24 | + | ||
| 25 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/template/PmsProjectTemplateRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.template; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 项目模板 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsProjectTemplateRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "敏捷研发模板") | ||
| 17 | + private String name; | ||
| 18 | + | ||
| 19 | + @Schema(description = "模板描述", example = "适用于标准敏捷研发项目") | ||
| 20 | + private String description; | ||
| 21 | + | ||
| 22 | + @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 23 | + private Integer projectType; | ||
| 24 | + | ||
| 25 | + @Schema(description = "模板状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||
| 26 | + private Integer status; | ||
| 27 | + | ||
| 28 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 29 | + private Integer sort; | ||
| 30 | + | ||
| 31 | + @Schema(description = "启用的工作项类型列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 32 | + private List<Integer> itemTypes; | ||
| 33 | + | ||
| 34 | + @Schema(description = "工作项状态模板列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 35 | + private List<PmsProjectTemplateSaveReqVO.StatusTemplate> statuses; | ||
| 36 | + | ||
| 37 | + @Schema(description = "看板列模板列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 38 | + private List<PmsProjectTemplateSaveReqVO.BoardTemplate> boards; | ||
| 39 | + | ||
| 40 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 41 | + private LocalDateTime createTime; | ||
| 42 | + | ||
| 43 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/project/vo/template/PmsProjectTemplateSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.project.vo.template; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 4 | +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectTypeEnum; | ||
| 5 | +import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemStatusTypeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemTypeEnum; | ||
| 7 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 8 | +import jakarta.validation.Valid; | ||
| 9 | +import jakarta.validation.constraints.NotBlank; | ||
| 10 | +import jakarta.validation.constraints.NotEmpty; | ||
| 11 | +import jakarta.validation.constraints.NotNull; | ||
| 12 | +import jakarta.validation.constraints.Size; | ||
| 13 | +import lombok.Data; | ||
| 14 | + | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 17 | +@Schema(description = "管理后台 - PMS 项目模板新增/修改 Request VO") | ||
| 18 | +@Data | ||
| 19 | +public class PmsProjectTemplateSaveReqVO { | ||
| 20 | + | ||
| 21 | + @Schema(description = "模板编号", example = "1024") | ||
| 22 | + private Long id; | ||
| 23 | + | ||
| 24 | + @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "敏捷研发模板") | ||
| 25 | + @NotBlank(message = "模板名称不能为空") | ||
| 26 | + @Size(max = 100, message = "模板名称不能超过 100 个字符") | ||
| 27 | + private String name; | ||
| 28 | + | ||
| 29 | + @Schema(description = "模板描述", example = "适用于标准敏捷研发项目") | ||
| 30 | + @Size(max = 500, message = "模板描述不能超过 500 个字符") | ||
| 31 | + private String description; | ||
| 32 | + | ||
| 33 | + @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 34 | + @NotNull(message = "项目类型不能为空") | ||
| 35 | + @InEnum(PmsProjectTypeEnum.class) | ||
| 36 | + private Integer projectType; | ||
| 37 | + | ||
| 38 | + @Schema(description = "模板状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | ||
| 39 | + @NotNull(message = "模板状态不能为空") | ||
| 40 | + private Integer status; | ||
| 41 | + | ||
| 42 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 43 | + @NotNull(message = "显示顺序不能为空") | ||
| 44 | + private Integer sort; | ||
| 45 | + | ||
| 46 | + @Schema(description = "启用的工作项类型列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[2, 3, 4]") | ||
| 47 | + @NotEmpty(message = "工作项类型不能为空") | ||
| 48 | + private List<Integer> itemTypes; | ||
| 49 | + | ||
| 50 | + @Schema(description = "工作项状态模板列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 51 | + @Valid | ||
| 52 | + @NotEmpty(message = "工作项状态不能为空") | ||
| 53 | + private List<StatusTemplate> statuses; | ||
| 54 | + | ||
| 55 | + @Schema(description = "看板列模板列表", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 56 | + @Valid | ||
| 57 | + @NotEmpty(message = "看板列不能为空") | ||
| 58 | + private List<BoardTemplate> boards; | ||
| 59 | + | ||
| 60 | + @Schema(description = "工作项状态模板") | ||
| 61 | + @Data | ||
| 62 | + public static class StatusTemplate { | ||
| 63 | + | ||
| 64 | + @Schema(description = "模板内稳定编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "task_todo") | ||
| 65 | + @NotBlank(message = "状态编码不能为空") | ||
| 66 | + @Size(max = 50, message = "状态编码不能超过 50 个字符") | ||
| 67 | + private String code; | ||
| 68 | + | ||
| 69 | + @Schema(description = "状态名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "待处理") | ||
| 70 | + @NotBlank(message = "状态名称不能为空") | ||
| 71 | + @Size(max = 50, message = "状态名称不能超过 50 个字符") | ||
| 72 | + private String name; | ||
| 73 | + | ||
| 74 | + @Schema(description = "工作项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 75 | + @NotNull(message = "状态工作项类型不能为空") | ||
| 76 | + @InEnum(PmsWorkItemTypeEnum.class) | ||
| 77 | + private Integer workItemType; | ||
| 78 | + | ||
| 79 | + @Schema(description = "语义状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 80 | + @NotNull(message = "语义状态不能为空") | ||
| 81 | + @InEnum(PmsWorkItemStatusTypeEnum.class) | ||
| 82 | + private Integer statusType; | ||
| 83 | + | ||
| 84 | + @Schema(description = "是否为初始状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 85 | + @NotNull(message = "是否为初始状态不能为空") | ||
| 86 | + private Boolean defaultStatus; | ||
| 87 | + | ||
| 88 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 89 | + @NotNull(message = "状态显示顺序不能为空") | ||
| 90 | + private Integer sort; | ||
| 91 | + | ||
| 92 | + @Schema(description = "所属看板列编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "todo") | ||
| 93 | + @NotBlank(message = "状态所属看板列不能为空") | ||
| 94 | + private String boardCode; | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + @Schema(description = "看板列模板") | ||
| 98 | + @Data | ||
| 99 | + public static class BoardTemplate { | ||
| 100 | + | ||
| 101 | + @Schema(description = "模板内稳定编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "todo") | ||
| 102 | + @NotBlank(message = "看板列编码不能为空") | ||
| 103 | + @Size(max = 50, message = "看板列编码不能超过 50 个字符") | ||
| 104 | + private String code; | ||
| 105 | + | ||
| 106 | + @Schema(description = "看板列名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "待处理") | ||
| 107 | + @NotBlank(message = "看板列名称不能为空") | ||
| 108 | + @Size(max = 50, message = "看板列名称不能超过 50 个字符") | ||
| 109 | + private String name; | ||
| 110 | + | ||
| 111 | + @Schema(description = "工作项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") | ||
| 112 | + @NotNull(message = "看板列工作项类型不能为空") | ||
| 113 | + @InEnum(PmsWorkItemTypeEnum.class) | ||
| 114 | + private Integer workItemType; | ||
| 115 | + | ||
| 116 | + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 117 | + @NotNull(message = "看板列显示顺序不能为空") | ||
| 118 | + private Integer sort; | ||
| 119 | + | ||
| 120 | + @Schema(description = "关联的状态编码列表", requiredMode = Schema.RequiredMode.REQUIRED, | ||
| 121 | + example = "[\"task_todo\"]") | ||
| 122 | + @NotEmpty(message = "看板列关联状态不能为空") | ||
| 123 | + private List<String> statusCodes; | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workbench/PmsWorkbenchController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workbench; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workbench.vo.PmsWorkbenchCountRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workbench.vo.PmsWorkbenchIterationRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workbench.vo.PmsWorkbenchPageReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workbench.vo.PmsWorkbenchWorkItemRespVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.iteration.PmsIterationDO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.project.PmsProjectDO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemDO; | ||
| 14 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemStatusDO; | ||
| 15 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectMemberService; | ||
| 16 | +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectService; | ||
| 17 | +import cn.iocoder.yudao.module.pms.service.pm.workbench.PmsWorkbenchService; | ||
| 18 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemStatusService; | ||
| 19 | +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | ||
| 20 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 21 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 22 | +import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; | ||
| 23 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 24 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 25 | +import jakarta.annotation.Resource; | ||
| 26 | +import jakarta.validation.Valid; | ||
| 27 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 28 | +import org.springframework.validation.annotation.Validated; | ||
| 29 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 30 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 31 | +import org.springframework.web.bind.annotation.RestController; | ||
| 32 | + | ||
| 33 | +import java.util.List; | ||
| 34 | +import java.util.Map; | ||
| 35 | +import java.util.Set; | ||
| 36 | + | ||
| 37 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 38 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 39 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 40 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 41 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 42 | + | ||
| 43 | +@Tag(name = "管理后台 - PMS 工作台") | ||
| 44 | +@RestController | ||
| 45 | +@RequestMapping("/pms/pm/workbench") | ||
| 46 | +@Validated | ||
| 47 | +public class PmsWorkbenchController { | ||
| 48 | + | ||
| 49 | + @Resource | ||
| 50 | + private PmsWorkbenchService workbenchService; | ||
| 51 | + @Resource | ||
| 52 | + private PmsProjectService projectService; | ||
| 53 | + @Resource | ||
| 54 | + private PmsProjectMemberService projectMemberService; | ||
| 55 | + @Resource | ||
| 56 | + private PmsWorkItemStatusService workItemStatusService; | ||
| 57 | + @Resource | ||
| 58 | + private PermissionApi permissionApi; | ||
| 59 | + @Resource | ||
| 60 | + private AdminUserApi adminUserApi; | ||
| 61 | + | ||
| 62 | + @GetMapping("/work-item-page") | ||
| 63 | + @Operation(summary = "获得我负责的工作项分页") | ||
| 64 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 65 | + public CommonResult<PageResult<PmsWorkbenchWorkItemRespVO>> getWorkbenchWorkItemPage( | ||
| 66 | + @Valid PmsWorkbenchPageReqVO pageReqVO) { | ||
| 67 | + // 1. 查询当前用户负责的工作项分页 | ||
| 68 | + Long userId = getLoginUserId(); | ||
| 69 | + PageResult<PmsWorkItemDO> pageResult = workbenchService.getWorkbenchWorkItemPage(pageReqVO, userId); | ||
| 70 | + // 2.1 批量查询项目、状态及项目写权限 | ||
| 71 | + Map<Long, PmsProjectDO> projectMap = projectService.getProjectMap( | ||
| 72 | + convertSet(pageResult.getList(), PmsWorkItemDO::getProjectId)); | ||
| 73 | + Map<Long, PmsWorkItemStatusDO> statusMap = workItemStatusService.getWorkItemStatusMap( | ||
| 74 | + convertSet(pageResult.getList(), PmsWorkItemDO::getStatusId)); | ||
| 75 | + Set<Long> writableProjectIds = convertSet(projectMemberService.getWritableProjectIdListByUserId(userId)); | ||
| 76 | + boolean superAdmin = permissionApi.hasAnyRoles(userId, RoleCodeEnum.SUPER_ADMIN.getCode()); | ||
| 77 | + // 2.2 批量查询负责人和创建人 | ||
| 78 | + Set<Long> userIds = convertSet(pageResult.getList(), PmsWorkItemDO::getAssigneeUserId); | ||
| 79 | + userIds.addAll(convertSet(pageResult.getList(), workItem -> NumberUtils.parseLong(workItem.getCreator()))); | ||
| 80 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||
| 81 | + Map<Long, Long> creatorUserIdMap = convertMap(pageResult.getList(), PmsWorkItemDO::getId, | ||
| 82 | + workItem -> NumberUtils.parseLong(workItem.getCreator())); | ||
| 83 | + // 3. 转换响应 VO,并拼接项目、状态、用户及写权限 | ||
| 84 | + List<PmsWorkbenchWorkItemRespVO> workItemVOList = BeanUtils.toBean(pageResult.getList(), | ||
| 85 | + PmsWorkbenchWorkItemRespVO.class, itemVO -> { | ||
| 86 | + findAndThen(projectMap, itemVO.getProjectId(), project -> itemVO | ||
| 87 | + .setProjectName(project.getName()).setProjectType(project.getType())); | ||
| 88 | + findAndThen(statusMap, itemVO.getStatusId(), status -> itemVO.setStatusName(status.getName())); | ||
| 89 | + findAndThen(userMap, itemVO.getAssigneeUserId(), | ||
| 90 | + user -> itemVO.setAssigneeUserName(user.getNickname())); | ||
| 91 | + itemVO.setCreatorUserId(creatorUserIdMap.get(itemVO.getId())); | ||
| 92 | + findAndThen(userMap, itemVO.getCreatorUserId(), | ||
| 93 | + user -> itemVO.setCreatorUserName(user.getNickname())); | ||
| 94 | + itemVO.setWriteStatus(superAdmin || writableProjectIds.contains(itemVO.getProjectId())); | ||
| 95 | + }); | ||
| 96 | + return success(new PageResult<>(workItemVOList, pageResult.getTotal())); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + @GetMapping("/iteration-page") | ||
| 100 | + @Operation(summary = "获得我负责的迭代分页") | ||
| 101 | + @PreAuthorize("@ss.hasPermission('pms:pm:iteration:query')") | ||
| 102 | + public CommonResult<PageResult<PmsWorkbenchIterationRespVO>> getWorkbenchIterationPage( | ||
| 103 | + @Valid PmsWorkbenchPageReqVO pageReqVO) { | ||
| 104 | + // 1.1 查询当前用户负责的迭代分页 | ||
| 105 | + PageResult<PmsIterationDO> pageResult = workbenchService.getWorkbenchIterationPage(pageReqVO, getLoginUserId()); | ||
| 106 | + // 1.2 批量查询关联项目 | ||
| 107 | + Map<Long, PmsProjectDO> projectMap = projectService.getProjectMap( | ||
| 108 | + convertSet(pageResult.getList(), PmsIterationDO::getProjectId)); | ||
| 109 | + // 2. 转换响应 VO,并拼接项目展示字段 | ||
| 110 | + List<PmsWorkbenchIterationRespVO> iterationVOList = BeanUtils.toBean(pageResult.getList(), | ||
| 111 | + PmsWorkbenchIterationRespVO.class, itemVO -> | ||
| 112 | + findAndThen(projectMap, itemVO.getProjectId(), project -> itemVO | ||
| 113 | + .setProjectName(project.getName()).setProjectType(project.getType()))); | ||
| 114 | + return success(new PageResult<>(iterationVOList, pageResult.getTotal())); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + @GetMapping("/count") | ||
| 118 | + @Operation(summary = "获得我的未完成事项数量") | ||
| 119 | + @PreAuthorize("@ss.hasAnyPermissions('pms:pm:work-item:query', 'pms:pm:iteration:query')") | ||
| 120 | + public CommonResult<PmsWorkbenchCountRespVO> getWorkbenchCount(PmsWorkbenchPageReqVO pageReqVO) { | ||
| 121 | + return success(workbenchService.getWorkbenchCount(pageReqVO, getLoginUserId())); | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workbench/vo/PmsWorkbenchCountRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workbench.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.experimental.Accessors; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - PMS 工作台数量响应 VO") | ||
| 8 | +@Data | ||
| 9 | +@Accessors(chain = true) | ||
| 10 | +public class PmsWorkbenchCountRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "需求数量", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 13 | + private Integer requirementCount; | ||
| 14 | + | ||
| 15 | + @Schema(description = "任务数量", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 16 | + private Integer taskCount; | ||
| 17 | + | ||
| 18 | + @Schema(description = "缺陷数量", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 19 | + private Integer defectCount; | ||
| 20 | + | ||
| 21 | + @Schema(description = "迭代数量", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 22 | + private Integer iterationCount; | ||
| 23 | + | ||
| 24 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workbench/vo/PmsWorkbenchIterationRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workbench.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 工作台迭代 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsWorkbenchIterationRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "迭代编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | ||
| 16 | + private Long projectId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "商城项目") | ||
| 19 | + private String projectName; | ||
| 20 | + | ||
| 21 | + @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 22 | + private Integer projectType; | ||
| 23 | + | ||
| 24 | + @Schema(description = "迭代名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "第一个迭代") | ||
| 25 | + private String name; | ||
| 26 | + | ||
| 27 | + @Schema(description = "迭代状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 28 | + private Integer status; | ||
| 29 | + | ||
| 30 | + @Schema(description = "开始时间", example = "2026-01-01 00:00:00") | ||
| 31 | + private LocalDateTime startTime; | ||
| 32 | + | ||
| 33 | + @Schema(description = "结束时间", example = "2026-01-31 23:59:59") | ||
| 34 | + private LocalDateTime endTime; | ||
| 35 | + | ||
| 36 | + @Schema(description = "迭代目标", example = "完成登录模块") | ||
| 37 | + private String target; | ||
| 38 | + | ||
| 39 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workbench/vo/PmsWorkbenchPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workbench.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemPriorityEnum; | ||
| 6 | +import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemTypeEnum; | ||
| 7 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 8 | +import lombok.Data; | ||
| 9 | +import lombok.EqualsAndHashCode; | ||
| 10 | +import lombok.ToString; | ||
| 11 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 12 | + | ||
| 13 | +import java.time.LocalDateTime; | ||
| 14 | + | ||
| 15 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 16 | + | ||
| 17 | +@Schema(description = "管理后台 - PMS 工作台分页 Request VO") | ||
| 18 | +@Data | ||
| 19 | +@EqualsAndHashCode(callSuper = true) | ||
| 20 | +@ToString(callSuper = true) | ||
| 21 | +public class PmsWorkbenchPageReqVO extends PageParam { | ||
| 22 | + | ||
| 23 | + @Schema(description = "项目编号", example = "1024") | ||
| 24 | + private Long projectId; | ||
| 25 | + | ||
| 26 | + @Schema(description = "工作项类型", example = "3") | ||
| 27 | + @InEnum(PmsWorkItemTypeEnum.class) | ||
| 28 | + private Integer type; | ||
| 29 | + | ||
| 30 | + @Schema(description = "名称", example = "登录") | ||
| 31 | + private String name; | ||
| 32 | + | ||
| 33 | + @Schema(description = "状态,工作项为语义状态,迭代为迭代状态", example = "2") | ||
| 34 | + private Integer status; | ||
| 35 | + | ||
| 36 | + @Schema(description = "优先级", example = "2") | ||
| 37 | + @InEnum(PmsWorkItemPriorityEnum.class) | ||
| 38 | + private Integer priority; | ||
| 39 | + | ||
| 40 | + @Schema(description = "迭代编号", example = "1024") | ||
| 41 | + private Long iterationId; | ||
| 42 | + | ||
| 43 | + @Schema(description = "截止时间范围") | ||
| 44 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 45 | + private LocalDateTime[] endTime; | ||
| 46 | + | ||
| 47 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workbench/vo/PmsWorkbenchWorkItemRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workbench.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 工作台工作项 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsWorkbenchWorkItemRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "工作项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | ||
| 16 | + private Long projectId; | ||
| 17 | + | ||
| 18 | + @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "商城项目") | ||
| 19 | + private String projectName; | ||
| 20 | + | ||
| 21 | + @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 22 | + private Integer projectType; | ||
| 23 | + | ||
| 24 | + @Schema(description = "工作项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 25 | + private Integer type; | ||
| 26 | + | ||
| 27 | + @Schema(description = "工作项序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 28 | + private Integer serialNumber; | ||
| 29 | + | ||
| 30 | + @Schema(description = "工作项名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "优化登录页") | ||
| 31 | + private String name; | ||
| 32 | + | ||
| 33 | + @Schema(description = "优先级", example = "2") | ||
| 34 | + private Integer priority; | ||
| 35 | + | ||
| 36 | + @Schema(description = "负责人用户编号", example = "1024") | ||
| 37 | + private Long assigneeUserId; | ||
| 38 | + | ||
| 39 | + @Schema(description = "负责人姓名", example = "芋道源码") | ||
| 40 | + private String assigneeUserName; | ||
| 41 | + | ||
| 42 | + @Schema(description = "创建人用户编号", example = "2048") | ||
| 43 | + private Long creatorUserId; | ||
| 44 | + | ||
| 45 | + @Schema(description = "创建人姓名", example = "源码") | ||
| 46 | + private String creatorUserName; | ||
| 47 | + | ||
| 48 | + @Schema(description = "状态编号", example = "1") | ||
| 49 | + private Long statusId; | ||
| 50 | + | ||
| 51 | + @Schema(description = "状态名称", example = "进行中") | ||
| 52 | + private String statusName; | ||
| 53 | + | ||
| 54 | + @Schema(description = "语义状态", example = "2") | ||
| 55 | + private Integer status; | ||
| 56 | + | ||
| 57 | + @Schema(description = "进度", example = "60") | ||
| 58 | + private Integer progress; | ||
| 59 | + | ||
| 60 | + @Schema(description = "开始时间", example = "2026-01-01 10:00:00") | ||
| 61 | + private LocalDateTime startTime; | ||
| 62 | + | ||
| 63 | + @Schema(description = "结束时间", example = "2026-01-31 18:00:00") | ||
| 64 | + private LocalDateTime endTime; | ||
| 65 | + | ||
| 66 | + @Schema(description = "是否可编辑", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 67 | + private Boolean writeStatus; | ||
| 68 | + | ||
| 69 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 70 | + private LocalDateTime createTime; | ||
| 71 | + | ||
| 72 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/PmsWorkItemActivityController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.activity.PmsWorkItemActivityRespVO; | ||
| 6 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemActivityDO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemActivityService; | ||
| 8 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemService; | ||
| 9 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 10 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 11 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 12 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 13 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 14 | +import jakarta.annotation.Resource; | ||
| 15 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 16 | +import org.springframework.validation.annotation.Validated; | ||
| 17 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 18 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 20 | +import org.springframework.web.bind.annotation.RestController; | ||
| 21 | + | ||
| 22 | +import java.util.List; | ||
| 23 | +import java.util.Map; | ||
| 24 | + | ||
| 25 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 26 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 27 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 28 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 29 | + | ||
| 30 | +@Tag(name = "管理后台 - PMS 工作项动态") | ||
| 31 | +@RestController | ||
| 32 | +@RequestMapping("/pms/pm/work-item-activity") | ||
| 33 | +@Validated | ||
| 34 | +public class PmsWorkItemActivityController { | ||
| 35 | + | ||
| 36 | + @Resource | ||
| 37 | + private PmsWorkItemActivityService activityService; | ||
| 38 | + @Resource | ||
| 39 | + private PmsWorkItemService workItemService; | ||
| 40 | + | ||
| 41 | + @Resource | ||
| 42 | + private AdminUserApi adminUserApi; | ||
| 43 | + | ||
| 44 | + @GetMapping("/list") | ||
| 45 | + @Operation(summary = "获得工作项动态列表") | ||
| 46 | + @Parameter(name = "workItemId", description = "工作项编号", required = true, example = "1024") | ||
| 47 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 48 | + public CommonResult<List<PmsWorkItemActivityRespVO>> getWorkItemActivityList( | ||
| 49 | + @RequestParam("workItemId") Long workItemId) { | ||
| 50 | + workItemService.getWorkItem(workItemId, getLoginUserId()); | ||
| 51 | + List<PmsWorkItemActivityDO> activities = activityService.getWorkItemActivityList(workItemId); | ||
| 52 | + // 拼接 VO:批量查询操作人,并补充用户展示字段 | ||
| 53 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( | ||
| 54 | + convertSet(activities, PmsWorkItemActivityDO::getOperatorUserId)); | ||
| 55 | + List<PmsWorkItemActivityRespVO> activityVOList = BeanUtils.toBean( | ||
| 56 | + activities, PmsWorkItemActivityRespVO.class, activityVO -> | ||
| 57 | + findAndThen(userMap, activityVO.getOperatorUserId(), user -> activityVO | ||
| 58 | + .setOperatorUserName(user.getNickname()).setOperatorUserAvatar(user.getAvatar()))); | ||
| 59 | + return success(activityVOList); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/PmsWorkItemCommentController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.comment.PmsWorkItemCommentRespVO; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.comment.PmsWorkItemCommentSaveReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemCommentDO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemCommentService; | ||
| 9 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 10 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 11 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 12 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 13 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 14 | +import jakarta.annotation.Resource; | ||
| 15 | +import jakarta.validation.Valid; | ||
| 16 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 17 | +import org.springframework.validation.annotation.Validated; | ||
| 18 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 21 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 23 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 25 | +import org.springframework.web.bind.annotation.RestController; | ||
| 26 | + | ||
| 27 | +import java.util.ArrayList; | ||
| 28 | +import java.util.LinkedHashMap; | ||
| 29 | +import java.util.List; | ||
| 30 | +import java.util.Map; | ||
| 31 | +import java.util.Set; | ||
| 32 | + | ||
| 33 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 35 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 36 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 37 | + | ||
| 38 | +@Tag(name = "管理后台 - PMS 工作项评论") | ||
| 39 | +@RestController | ||
| 40 | +@RequestMapping("/pms/pm/work-item-comment") | ||
| 41 | +@Validated | ||
| 42 | +public class PmsWorkItemCommentController { | ||
| 43 | + | ||
| 44 | + @Resource | ||
| 45 | + private PmsWorkItemCommentService commentService; | ||
| 46 | + | ||
| 47 | + @Resource | ||
| 48 | + private AdminUserApi adminUserApi; | ||
| 49 | + | ||
| 50 | + @PostMapping("/create") | ||
| 51 | + @Operation(summary = "创建工作项评论") | ||
| 52 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 53 | + public CommonResult<Long> createWorkItemComment(@Valid @RequestBody PmsWorkItemCommentSaveReqVO saveReqVO) { | ||
| 54 | + return success(commentService.createWorkItemComment(saveReqVO, getLoginUserId())); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @PutMapping("/update") | ||
| 58 | + @Operation(summary = "修改工作项评论") | ||
| 59 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 60 | + public CommonResult<Boolean> updateWorkItemComment(@Valid @RequestBody PmsWorkItemCommentSaveReqVO saveReqVO) { | ||
| 61 | + commentService.updateWorkItemComment(saveReqVO, getLoginUserId()); | ||
| 62 | + return success(true); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @DeleteMapping("/delete") | ||
| 66 | + @Operation(summary = "删除工作项评论") | ||
| 67 | + @Parameter(name = "id", description = "评论编号", required = true, example = "1024") | ||
| 68 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 69 | + public CommonResult<Boolean> deleteWorkItemComment(@RequestParam("id") Long id) { | ||
| 70 | + commentService.deleteWorkItemComment(id, getLoginUserId()); | ||
| 71 | + return success(true); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + @GetMapping("/list") | ||
| 75 | + @Operation(summary = "获得工作项评论列表") | ||
| 76 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 77 | + public CommonResult<List<PmsWorkItemCommentRespVO>> getWorkItemCommentList( | ||
| 78 | + @RequestParam("workItemId") Long workItemId) { | ||
| 79 | + List<PmsWorkItemCommentDO> comments = commentService.getWorkItemCommentList(workItemId, getLoginUserId()); | ||
| 80 | + // 拼接 VO:批量查询评论人和回复对象 | ||
| 81 | + Set<Long> userIds = convertSet(comments, PmsWorkItemCommentDO::getUserId); | ||
| 82 | + userIds.addAll(convertSet(comments, PmsWorkItemCommentDO::getReplyUserId)); | ||
| 83 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||
| 84 | + // 拼接 VO:转换评论,并按主评论组织回复列表 | ||
| 85 | + Map<Long, PmsWorkItemCommentRespVO> mainCommentMap = new LinkedHashMap<>(); | ||
| 86 | + List<PmsWorkItemCommentRespVO> mainComments = new ArrayList<>(); | ||
| 87 | + for (PmsWorkItemCommentDO comment : comments) { | ||
| 88 | + PmsWorkItemCommentRespVO commentVO = BeanUtils.toBean(comment, PmsWorkItemCommentRespVO.class).setChildren(new ArrayList<>()); | ||
| 89 | + findAndThen(userMap, comment.getUserId(), user -> commentVO.setUserName(user.getNickname())); | ||
| 90 | + findAndThen(userMap, comment.getReplyUserId(), user -> commentVO.setReplyUserName(user.getNickname())); | ||
| 91 | + if (PmsWorkItemCommentDO.MAIN_ID_ROOT.equals(comment.getMainId())) { | ||
| 92 | + mainCommentMap.put(comment.getId(), commentVO); | ||
| 93 | + mainComments.add(commentVO); | ||
| 94 | + } else { | ||
| 95 | + PmsWorkItemCommentRespVO mainComment = mainCommentMap.get(comment.getMainId()); | ||
| 96 | + if (mainComment != null) { | ||
| 97 | + mainComment.getChildren().add(commentVO); | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + return success(mainComments); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/PmsWorkItemController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 7 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 8 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.label.PmsWorkItemLabelRespVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.status.PmsWorkItemStatusUpdateReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemBoardReqVO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemBoardRespVO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemImportExcelVO; | ||
| 14 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemImportRespVO; | ||
| 15 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemIterationUpdateReqVO; | ||
| 16 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemNameUpdateReqVO; | ||
| 17 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemPageReqVO; | ||
| 18 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemPlanningSortReqVO; | ||
| 19 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemRespVO; | ||
| 20 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemSaveReqVO; | ||
| 21 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem.PmsWorkItemSortReqVO; | ||
| 22 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.iteration.PmsIterationDO; | ||
| 23 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemDO; | ||
| 24 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemLabelDO; | ||
| 25 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemStatusDO; | ||
| 26 | +import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemPriorityEnum; | ||
| 27 | +import cn.iocoder.yudao.module.pms.service.pm.iteration.PmsIterationService; | ||
| 28 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemLabelService; | ||
| 29 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemService; | ||
| 30 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemStatusService; | ||
| 31 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 32 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 33 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 34 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 35 | +import io.swagger.v3.oas.annotations.Parameters; | ||
| 36 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 37 | +import jakarta.annotation.Resource; | ||
| 38 | +import jakarta.servlet.http.HttpServletResponse; | ||
| 39 | +import jakarta.validation.Valid; | ||
| 40 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 41 | +import org.springframework.validation.annotation.Validated; | ||
| 42 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 43 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 44 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 45 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 46 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 47 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 48 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 49 | +import org.springframework.web.bind.annotation.RestController; | ||
| 50 | +import org.springframework.web.multipart.MultipartFile; | ||
| 51 | + | ||
| 52 | +import java.io.IOException; | ||
| 53 | +import java.time.LocalDateTime; | ||
| 54 | +import java.util.Collections; | ||
| 55 | +import java.util.List; | ||
| 56 | +import java.util.Map; | ||
| 57 | +import java.util.Set; | ||
| 58 | + | ||
| 59 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 60 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 61 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; | ||
| 62 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 63 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; | ||
| 64 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 65 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 66 | + | ||
| 67 | +@Tag(name = "管理后台 - PMS 工作项") | ||
| 68 | +@RestController | ||
| 69 | +@RequestMapping("/pms/pm/work-item") | ||
| 70 | +@Validated | ||
| 71 | +public class PmsWorkItemController { | ||
| 72 | + | ||
| 73 | + @Resource | ||
| 74 | + private PmsWorkItemService workItemService; | ||
| 75 | + @Resource | ||
| 76 | + private PmsWorkItemLabelService workItemLabelService; | ||
| 77 | + @Resource | ||
| 78 | + private PmsWorkItemStatusService workItemStatusService; | ||
| 79 | + @Resource | ||
| 80 | + private PmsIterationService iterationService; | ||
| 81 | + | ||
| 82 | + @Resource | ||
| 83 | + private AdminUserApi adminUserApi; | ||
| 84 | + | ||
| 85 | + @PostMapping("/create") | ||
| 86 | + @Operation(summary = "创建工作项") | ||
| 87 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:create')") | ||
| 88 | + public CommonResult<Long> createWorkItem(@Valid @RequestBody PmsWorkItemSaveReqVO saveReqVO) { | ||
| 89 | + return success(workItemService.createWorkItem(saveReqVO, getLoginUserId())); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + @PutMapping("/update") | ||
| 93 | + @Operation(summary = "更新工作项") | ||
| 94 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 95 | + public CommonResult<Boolean> updateWorkItem(@Valid @RequestBody PmsWorkItemSaveReqVO saveReqVO) { | ||
| 96 | + workItemService.updateWorkItem(saveReqVO, getLoginUserId()); | ||
| 97 | + return success(true); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + @PutMapping("/update-name") | ||
| 101 | + @Operation(summary = "更新工作项名称") | ||
| 102 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 103 | + public CommonResult<Boolean> updateWorkItemName(@Valid @RequestBody PmsWorkItemNameUpdateReqVO updateReqVO) { | ||
| 104 | + workItemService.updateWorkItemName(updateReqVO, getLoginUserId()); | ||
| 105 | + return success(true); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + @PutMapping("/update-status") | ||
| 109 | + @Operation(summary = "更新工作项状态") | ||
| 110 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 111 | + public CommonResult<Boolean> updateWorkItemStatus(@Valid @RequestBody PmsWorkItemStatusUpdateReqVO updateReqVO) { | ||
| 112 | + workItemService.updateWorkItemStatus(updateReqVO, getLoginUserId()); | ||
| 113 | + return success(true); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + @PutMapping("/update-iteration") | ||
| 117 | + @Operation(summary = "更新工作项所属迭代") | ||
| 118 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 119 | + public CommonResult<Boolean> updateWorkItemIteration(@Valid @RequestBody PmsWorkItemIterationUpdateReqVO updateReqVO) { | ||
| 120 | + workItemService.updateWorkItemIteration(updateReqVO, getLoginUserId()); | ||
| 121 | + return success(true); | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + @PutMapping("/update-sort") | ||
| 125 | + @Operation(summary = "更新看板列内工作项顺序") | ||
| 126 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 127 | + public CommonResult<Boolean> updateWorkItemSort(@Valid @RequestBody PmsWorkItemSortReqVO sortReqVO) { | ||
| 128 | + workItemService.updateWorkItemSort(sortReqVO, getLoginUserId()); | ||
| 129 | + return success(true); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + @PutMapping("/update-planning-sort") | ||
| 133 | + @Operation(summary = "更新待规划或迭代内工作项顺序") | ||
| 134 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 135 | + public CommonResult<Boolean> updateWorkItemPlanningSort(@Valid @RequestBody PmsWorkItemPlanningSortReqVO sortReqVO) { | ||
| 136 | + workItemService.updateWorkItemPlanningSort(sortReqVO, getLoginUserId()); | ||
| 137 | + return success(true); | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + @PutMapping("/archive") | ||
| 141 | + @Operation(summary = "归档工作项") | ||
| 142 | + @Parameter(name = "id", description = "工作项编号", required = true, example = "1024") | ||
| 143 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 144 | + public CommonResult<Boolean> archiveWorkItem(@RequestParam("id") Long id) { | ||
| 145 | + workItemService.archiveWorkItem(id, getLoginUserId()); | ||
| 146 | + return success(true); | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + @PutMapping("/recycle") | ||
| 150 | + @Operation(summary = "将工作项移入回收站") | ||
| 151 | + @Parameter(name = "id", description = "工作项编号", required = true, example = "1024") | ||
| 152 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 153 | + public CommonResult<Boolean> recycleWorkItem(@RequestParam("id") Long id) { | ||
| 154 | + workItemService.recycleWorkItem(id, getLoginUserId()); | ||
| 155 | + return success(true); | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + @PutMapping("/restore") | ||
| 159 | + @Operation(summary = "恢复工作项") | ||
| 160 | + @Parameter(name = "id", description = "工作项编号", required = true, example = "1024") | ||
| 161 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 162 | + public CommonResult<Boolean> restoreWorkItem(@RequestParam("id") Long id) { | ||
| 163 | + workItemService.restoreWorkItem(id, getLoginUserId()); | ||
| 164 | + return success(true); | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + @DeleteMapping("/delete") | ||
| 168 | + @Operation(summary = "彻底删除回收站中的工作项") | ||
| 169 | + @Parameter(name = "id", description = "工作项编号", required = true, example = "1024") | ||
| 170 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:delete')") | ||
| 171 | + public CommonResult<Boolean> deleteWorkItem(@RequestParam("id") Long id) { | ||
| 172 | + workItemService.deleteWorkItem(id, getLoginUserId()); | ||
| 173 | + return success(true); | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + @GetMapping("/get") | ||
| 177 | + @Operation(summary = "获得工作项详情") | ||
| 178 | + @Parameter(name = "id", description = "工作项编号", required = true, example = "1024") | ||
| 179 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 180 | + public CommonResult<PmsWorkItemRespVO> getWorkItem(@RequestParam("id") Long id) { | ||
| 181 | + PmsWorkItemDO workItem = workItemService.getWorkItem(id, getLoginUserId()); | ||
| 182 | + PmsWorkItemRespVO workItemVO = buildWorkItemRespVO(workItem); | ||
| 183 | + return success(workItemVO); | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + @GetMapping("/page") | ||
| 187 | + @Operation(summary = "获得工作项分页") | ||
| 188 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 189 | + public CommonResult<PageResult<PmsWorkItemRespVO>> getWorkItemPage(@Valid PmsWorkItemPageReqVO pageReqVO) { | ||
| 190 | + PageResult<PmsWorkItemDO> pageResult = workItemService.getWorkItemPage(pageReqVO, getLoginUserId()); | ||
| 191 | + return success(new PageResult<>(buildWorkItemRespVOList(pageResult.getList()), pageResult.getTotal())); | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + @GetMapping("/export-excel") | ||
| 195 | + @Operation(summary = "导出工作项") | ||
| 196 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:export')") | ||
| 197 | + public void exportWorkItemList(@Valid PmsWorkItemPageReqVO pageReqVO, | ||
| 198 | + HttpServletResponse response) throws IOException { | ||
| 199 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | ||
| 200 | + List<PmsWorkItemDO> list = workItemService.getWorkItemList(pageReqVO, getLoginUserId()); | ||
| 201 | + List<PmsWorkItemRespVO> workItemVOList = buildWorkItemRespVOList(list); | ||
| 202 | + ExcelUtils.write(response, "工作项.xlsx", "工作项", PmsWorkItemRespVO.class, workItemVOList); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + @GetMapping("/get-import-template") | ||
| 206 | + @Operation(summary = "下载工作项导入模板") | ||
| 207 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:import')") | ||
| 208 | + public void getWorkItemImportTemplate(HttpServletResponse response) throws IOException { | ||
| 209 | + LocalDateTime now = LocalDateTime.now(); | ||
| 210 | + LocalDateTime deadline = now.plusDays(3); | ||
| 211 | + PmsWorkItemImportExcelVO example = PmsWorkItemImportExcelVO.builder() | ||
| 212 | + .name("登录页面开发").description("实现账号密码登录").statusName("") | ||
| 213 | + .priority(PmsWorkItemPriorityEnum.MEDIUM.getPriority()) | ||
| 214 | + .startTime(now).endTime(deadline) | ||
| 215 | + .labels(Collections.emptyList()).progress(0).estimatedHours(16) | ||
| 216 | + .build(); | ||
| 217 | + ExcelUtils.write(response, "工作项导入模板.xlsx", "工作项", PmsWorkItemImportExcelVO.class, | ||
| 218 | + Collections.singletonList(example)); | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + @PostMapping("/import") | ||
| 222 | + @Operation(summary = "导入工作项") | ||
| 223 | + @Parameters({ | ||
| 224 | + @Parameter(name = "projectId", description = "项目编号", required = true, example = "1024"), | ||
| 225 | + @Parameter(name = "type", description = "工作项类型(需求、任务、缺陷)", required = true, example = "1"), | ||
| 226 | + @Parameter(name = "file", description = "Excel 文件", required = true) | ||
| 227 | + }) | ||
| 228 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:import')") | ||
| 229 | + public CommonResult<PmsWorkItemImportRespVO> importWorkItemList( | ||
| 230 | + @RequestParam("projectId") Long projectId, | ||
| 231 | + @RequestParam("type") Integer workItemType, | ||
| 232 | + @RequestParam("file") MultipartFile file) throws Exception { | ||
| 233 | + return success(workItemService.importWorkItemList(projectId, workItemType, | ||
| 234 | + ExcelUtils.read(file, PmsWorkItemImportExcelVO.class), getLoginUserId())); | ||
| 235 | + } | ||
| 236 | + | ||
| 237 | + @GetMapping("/board") | ||
| 238 | + @Operation(summary = "获得工作项看板") | ||
| 239 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 240 | + public CommonResult<List<PmsWorkItemBoardRespVO>> getWorkItemBoard(@Valid PmsWorkItemBoardReqVO queryReqVO) { | ||
| 241 | + List<PmsWorkItemBoardRespVO> columns = workItemService.getWorkItemBoard(queryReqVO, getLoginUserId()); | ||
| 242 | + fillWorkItemRespVOList(convertListByFlatMap(columns, column -> column.getItems().stream())); | ||
| 243 | + return success(columns); | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + // ==================== 拼接 VO ==================== | ||
| 247 | + | ||
| 248 | + private PmsWorkItemRespVO buildWorkItemRespVO(PmsWorkItemDO workItem) { | ||
| 249 | + return CollUtil.getFirst(buildWorkItemRespVOList(Collections.singletonList(workItem))); | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + private List<PmsWorkItemRespVO> buildWorkItemRespVOList(List<PmsWorkItemDO> workItems) { | ||
| 253 | + if (CollUtil.isEmpty(workItems)) { | ||
| 254 | + return Collections.emptyList(); | ||
| 255 | + } | ||
| 256 | + return fillWorkItemRespVOList(BeanUtils.toBean(workItems, PmsWorkItemRespVO.class)); | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + private List<PmsWorkItemRespVO> fillWorkItemRespVOList(List<PmsWorkItemRespVO> workItems) { | ||
| 260 | + if (CollUtil.isEmpty(workItems)) { | ||
| 261 | + return Collections.emptyList(); | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + // 1.1 批量查询状态、迭代、关联需求和参与人 | ||
| 265 | + Map<Long, PmsWorkItemStatusDO> statusMap = workItemStatusService.getWorkItemStatusMap( | ||
| 266 | + convertSet(workItems, PmsWorkItemRespVO::getStatusId)); | ||
| 267 | + Map<Long, PmsIterationDO> iterationMap = iterationService.getIterationMap( | ||
| 268 | + convertSet(workItems, PmsWorkItemRespVO::getIterationId)); | ||
| 269 | + Map<Long, PmsWorkItemDO> requirementMap = workItemService.getWorkItemMap( | ||
| 270 | + convertSet(workItems, PmsWorkItemRespVO::getRelatedRequirementId)); | ||
| 271 | + Map<Long, List<Long>> memberUserIdListMap = workItemService.getWorkItemMemberUserIdListMap( | ||
| 272 | + convertSet(workItems, PmsWorkItemRespVO::getId)); | ||
| 273 | + Map<Long, PmsWorkItemLabelDO> labelMap = workItemLabelService.getWorkItemLabelMap( | ||
| 274 | + convertSetByFlatMap(workItems, PmsWorkItemRespVO::getLabelIds, List::stream)); | ||
| 275 | + // 1.2 批量查询负责人和参与人用户 | ||
| 276 | + Set<Long> userIds = convertSetByFlatMap(workItems, workItem -> java.util.stream.Stream.concat( | ||
| 277 | + java.util.stream.Stream.of(workItem.getAssigneeUserId()), | ||
| 278 | + memberUserIdListMap.getOrDefault(workItem.getId(), Collections.emptyList()).stream())); | ||
| 279 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds); | ||
| 280 | + // 2. 拼接工作项展示字段 | ||
| 281 | + for (PmsWorkItemRespVO workItemVO : workItems) { | ||
| 282 | + findAndThen(statusMap, workItemVO.getStatusId(), status -> workItemVO.setStatusName(status.getName())); | ||
| 283 | + findAndThen(iterationMap, workItemVO.getIterationId(), | ||
| 284 | + iteration -> workItemVO.setIterationName(iteration.getName())); | ||
| 285 | + findAndThen(requirementMap, workItemVO.getRelatedRequirementId(), | ||
| 286 | + requirement -> workItemVO.setRelatedRequirementName(requirement.getName())); | ||
| 287 | + findAndThen(userMap, workItemVO.getAssigneeUserId(), | ||
| 288 | + assignee -> workItemVO.setAssigneeUserName(assignee.getNickname())); | ||
| 289 | + List<Long> memberUserIds = memberUserIdListMap.getOrDefault(workItemVO.getId(), Collections.emptyList()); | ||
| 290 | + List<String> memberUserNames = convertList(convertList(memberUserIds, userMap::get), | ||
| 291 | + AdminUserRespDTO::getNickname); | ||
| 292 | + workItemVO.setMemberUserIds(memberUserIds).setMemberUserNames(memberUserNames); | ||
| 293 | + workItemVO.setLabels(BeanUtils.toBean(convertList(workItemVO.getLabelIds(), labelMap::get), | ||
| 294 | + PmsWorkItemLabelRespVO.class)); | ||
| 295 | + } | ||
| 296 | + return workItems; | ||
| 297 | + } | ||
| 298 | + | ||
| 299 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/PmsWorkItemLabelController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 5 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.label.PmsWorkItemLabelRespVO; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.label.PmsWorkItemLabelSaveReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemLabelDO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemLabelService; | ||
| 9 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 10 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 11 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 12 | +import jakarta.annotation.Resource; | ||
| 13 | +import jakarta.validation.Valid; | ||
| 14 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 15 | +import org.springframework.validation.annotation.Validated; | ||
| 16 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 17 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 18 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 19 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 20 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 21 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 22 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 23 | +import org.springframework.web.bind.annotation.RestController; | ||
| 24 | + | ||
| 25 | +import java.util.List; | ||
| 26 | + | ||
| 27 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 28 | + | ||
| 29 | +@Tag(name = "管理后台 - PMS 工作项标签") | ||
| 30 | +@RestController | ||
| 31 | +@RequestMapping("/pms/pm/work-item-label") | ||
| 32 | +@Validated | ||
| 33 | +public class PmsWorkItemLabelController { | ||
| 34 | + | ||
| 35 | + @Resource | ||
| 36 | + private PmsWorkItemLabelService labelService; | ||
| 37 | + | ||
| 38 | + @PostMapping("/create") | ||
| 39 | + @Operation(summary = "创建工作项标签") | ||
| 40 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 41 | + public CommonResult<Long> createWorkItemLabel(@Valid @RequestBody PmsWorkItemLabelSaveReqVO saveReqVO) { | ||
| 42 | + return success(labelService.createWorkItemLabel(saveReqVO)); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + @PutMapping("/update") | ||
| 46 | + @Operation(summary = "修改工作项标签") | ||
| 47 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 48 | + public CommonResult<Boolean> updateWorkItemLabel(@Valid @RequestBody PmsWorkItemLabelSaveReqVO saveReqVO) { | ||
| 49 | + labelService.updateWorkItemLabel(saveReqVO); | ||
| 50 | + return success(true); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + @DeleteMapping("/delete") | ||
| 54 | + @Operation(summary = "删除工作项标签") | ||
| 55 | + @Parameter(name = "id", description = "标签编号", required = true, example = "1024") | ||
| 56 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 57 | + public CommonResult<Boolean> deleteWorkItemLabel(@RequestParam("id") Long id) { | ||
| 58 | + labelService.deleteWorkItemLabel(id); | ||
| 59 | + return success(true); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + @GetMapping("/list") | ||
| 63 | + @Operation(summary = "获得工作项标签列表") | ||
| 64 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 65 | + public CommonResult<List<PmsWorkItemLabelRespVO>> getWorkItemLabelList( | ||
| 66 | + @RequestParam(value = "name", required = false) String name) { | ||
| 67 | + List<PmsWorkItemLabelDO> labels = labelService.getWorkItemLabelList(name); | ||
| 68 | + return success(BeanUtils.toBean(labels, PmsWorkItemLabelRespVO.class)); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/PmsWorkItemStatusController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.status.PmsWorkItemBoardConfigRespVO; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.status.PmsWorkItemBoardConfigSaveReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.status.PmsWorkItemStatusConfigUpdateReqVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.status.PmsWorkItemStatusCreateReqVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.status.PmsWorkItemStatusDeleteReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.status.PmsWorkItemStatusRespVO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.status.PmsWorkItemStatusSortReqVO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemBoardDO; | ||
| 14 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemStatusDO; | ||
| 15 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemStatusService; | ||
| 16 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 17 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 18 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 19 | +import jakarta.annotation.Resource; | ||
| 20 | +import jakarta.validation.Valid; | ||
| 21 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 22 | +import org.springframework.validation.annotation.Validated; | ||
| 23 | +import org.springframework.web.bind.annotation.DeleteMapping; | ||
| 24 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 25 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 27 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 28 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 29 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 30 | +import org.springframework.web.bind.annotation.RestController; | ||
| 31 | + | ||
| 32 | +import java.util.ArrayList; | ||
| 33 | +import java.util.LinkedHashMap; | ||
| 34 | +import java.util.LinkedHashSet; | ||
| 35 | +import java.util.List; | ||
| 36 | +import java.util.Map; | ||
| 37 | +import java.util.Set; | ||
| 38 | + | ||
| 39 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 40 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 41 | + | ||
| 42 | +@Tag(name = "管理后台 - PMS 工作项状态") | ||
| 43 | +@RestController | ||
| 44 | +@RequestMapping("/pms/pm/work-item-status") | ||
| 45 | +@Validated | ||
| 46 | +public class PmsWorkItemStatusController { | ||
| 47 | + | ||
| 48 | + @Resource | ||
| 49 | + private PmsWorkItemStatusService workItemStatusService; | ||
| 50 | + | ||
| 51 | + @PostMapping("/create") | ||
| 52 | + @Operation(summary = "创建工作项状态") | ||
| 53 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 54 | + public CommonResult<Long> createWorkItemStatus( | ||
| 55 | + @Valid @RequestBody PmsWorkItemStatusCreateReqVO createReqVO) { | ||
| 56 | + return success(workItemStatusService.createWorkItemStatus(createReqVO, getLoginUserId())); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + @PutMapping("/update") | ||
| 60 | + @Operation(summary = "更新工作项状态") | ||
| 61 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 62 | + public CommonResult<Boolean> updateWorkItemStatusConfig( | ||
| 63 | + @Valid @RequestBody PmsWorkItemStatusConfigUpdateReqVO updateReqVO) { | ||
| 64 | + workItemStatusService.updateWorkItemStatusConfig(updateReqVO, getLoginUserId()); | ||
| 65 | + return success(true); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + @PutMapping("/update-default") | ||
| 69 | + @Operation(summary = "更新工作项初始状态") | ||
| 70 | + @Parameter(name = "id", description = "状态编号", required = true, example = "1024") | ||
| 71 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 72 | + public CommonResult<Boolean> updateDefaultWorkItemStatus(@RequestParam("id") Long id) { | ||
| 73 | + workItemStatusService.updateDefaultWorkItemStatus(id, getLoginUserId()); | ||
| 74 | + return success(true); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @PutMapping("/update-sort") | ||
| 78 | + @Operation(summary = "更新工作项状态顺序") | ||
| 79 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 80 | + public CommonResult<Boolean> updateWorkItemStatusSort( | ||
| 81 | + @Valid @RequestBody PmsWorkItemStatusSortReqVO sortReqVO) { | ||
| 82 | + workItemStatusService.updateWorkItemStatusSort(sortReqVO, getLoginUserId()); | ||
| 83 | + return success(true); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + @PutMapping("/update-board-config") | ||
| 87 | + @Operation(summary = "更新工作项看板列和状态映射") | ||
| 88 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 89 | + public CommonResult<Boolean> updateWorkItemBoardConfig( | ||
| 90 | + @Valid @RequestBody PmsWorkItemBoardConfigSaveReqVO saveReqVO) { | ||
| 91 | + workItemStatusService.updateWorkItemBoardConfig(saveReqVO, getLoginUserId()); | ||
| 92 | + return success(true); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + @DeleteMapping("/delete") | ||
| 96 | + @Operation(summary = "删除工作项状态并迁移工作项") | ||
| 97 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 98 | + public CommonResult<Boolean> deleteWorkItemStatus( | ||
| 99 | + @Valid @RequestBody PmsWorkItemStatusDeleteReqVO deleteReqVO) { | ||
| 100 | + workItemStatusService.deleteWorkItemStatus(deleteReqVO, getLoginUserId()); | ||
| 101 | + return success(true); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + @GetMapping("/get") | ||
| 105 | + @Operation(summary = "获得工作项状态详情") | ||
| 106 | + @Parameter(name = "id", description = "状态编号", required = true, example = "1024") | ||
| 107 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 108 | + public CommonResult<PmsWorkItemStatusRespVO> getWorkItemStatus(@RequestParam("id") Long id) { | ||
| 109 | + PmsWorkItemStatusDO status = workItemStatusService.getWorkItemStatus(id, getLoginUserId()); | ||
| 110 | + return success(BeanUtils.toBean(status, PmsWorkItemStatusRespVO.class)); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + @GetMapping("/list") | ||
| 114 | + @Operation(summary = "获得工作项看板状态列表") | ||
| 115 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 116 | + public CommonResult<List<PmsWorkItemStatusRespVO>> getWorkItemStatusList( | ||
| 117 | + @RequestParam("projectId") Long projectId, @RequestParam("type") Integer workItemType) { | ||
| 118 | + List<PmsWorkItemStatusDO> statuses = workItemStatusService.getWorkItemStatusList(projectId, workItemType, | ||
| 119 | + getLoginUserId()); | ||
| 120 | + return success(BeanUtils.toBean(statuses, PmsWorkItemStatusRespVO.class)); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + @GetMapping("/get-board-config") | ||
| 124 | + @Operation(summary = "获得工作项看板列和状态映射") | ||
| 125 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 126 | + public CommonResult<PmsWorkItemBoardConfigRespVO> getWorkItemBoardConfig( | ||
| 127 | + @RequestParam("projectId") Long projectId, @RequestParam("type") Integer workItemType) { | ||
| 128 | + // 1. 校验项目可读并查询已保存的看板列、状态 | ||
| 129 | + List<PmsWorkItemStatusDO> statuses = workItemStatusService | ||
| 130 | + .getWorkItemStatusList(projectId, workItemType, getLoginUserId()); | ||
| 131 | + List<PmsWorkItemBoardDO> boards = workItemStatusService.getWorkItemBoardList(projectId, workItemType); | ||
| 132 | + | ||
| 133 | + // 2.1 按看板列名称聚合状态编号 | ||
| 134 | + Map<String, List<Long>> statusIdMap = new LinkedHashMap<>(); | ||
| 135 | + for (PmsWorkItemStatusDO status : statuses) { | ||
| 136 | + if (StrUtil.isNotBlank(status.getBoardName())) { | ||
| 137 | + statusIdMap.computeIfAbsent(status.getBoardName(), key -> new ArrayList<>()).add(status.getId()); | ||
| 138 | + } | ||
| 139 | + } | ||
| 140 | + // 2.2 按看板列顺序组装响应,并保留空列 | ||
| 141 | + Set<Long> assignedStatusIds = new LinkedHashSet<>(); | ||
| 142 | + List<PmsWorkItemBoardConfigRespVO.Board> boardVOs = new ArrayList<>(); | ||
| 143 | + for (PmsWorkItemBoardDO board : boards) { | ||
| 144 | + List<Long> statusIds = statusIdMap.getOrDefault(board.getName(), new ArrayList<>()); | ||
| 145 | + assignedStatusIds.addAll(statusIds); | ||
| 146 | + boardVOs.add(new PmsWorkItemBoardConfigRespVO.Board().setId(board.getId()) | ||
| 147 | + .setName(board.getName()).setStatusIds(statusIds)); | ||
| 148 | + } | ||
| 149 | + // 2.3 收集未分配到看板列的状态 | ||
| 150 | + List<Long> unassignedStatusIds = new ArrayList<>(); | ||
| 151 | + for (PmsWorkItemStatusDO status : statuses) { | ||
| 152 | + if (!assignedStatusIds.contains(status.getId())) { | ||
| 153 | + unassignedStatusIds.add(status.getId()); | ||
| 154 | + } | ||
| 155 | + } | ||
| 156 | + return success(new PmsWorkItemBoardConfigRespVO().setBoards(boardVOs).setUnassignedStatusIds(unassignedStatusIds)); | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/PmsWorkItemWorkLogController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; | ||
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 7 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.worklog.PmsProjectWorkLogReportReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.worklog.PmsProjectWorkLogReportRespVO; | ||
| 9 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.worklog.PmsWorkItemWorkLogRespVO; | ||
| 10 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.worklog.PmsWorkItemWorkLogSaveReqVO; | ||
| 11 | +import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.worklog.PmsWorkItemWorkLogSummaryRespVO; | ||
| 12 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemDO; | ||
| 13 | +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemWorkLogDO; | ||
| 14 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemService; | ||
| 15 | +import cn.iocoder.yudao.module.pms.service.pm.workitem.PmsWorkItemWorkLogService; | ||
| 16 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 17 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||
| 18 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 19 | +import io.swagger.v3.oas.annotations.Parameter; | ||
| 20 | +import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 21 | +import jakarta.annotation.Resource; | ||
| 22 | +import jakarta.validation.Valid; | ||
| 23 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 24 | +import org.springframework.validation.annotation.Validated; | ||
| 25 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 26 | +import org.springframework.web.bind.annotation.PostMapping; | ||
| 27 | +import org.springframework.web.bind.annotation.PutMapping; | ||
| 28 | +import org.springframework.web.bind.annotation.RequestBody; | ||
| 29 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 30 | +import org.springframework.web.bind.annotation.RequestParam; | ||
| 31 | +import org.springframework.web.bind.annotation.RestController; | ||
| 32 | + | ||
| 33 | +import java.util.Collections; | ||
| 34 | +import java.util.List; | ||
| 35 | +import java.util.Map; | ||
| 36 | +import java.util.Set; | ||
| 37 | + | ||
| 38 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 39 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 40 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 41 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 42 | + | ||
| 43 | +@Tag(name = "管理后台 - PMS 工作项工时") | ||
| 44 | +@RestController | ||
| 45 | +@RequestMapping("/pms/pm/work-item-work-log") | ||
| 46 | +@Validated | ||
| 47 | +public class PmsWorkItemWorkLogController { | ||
| 48 | + | ||
| 49 | + @Resource | ||
| 50 | + private PmsWorkItemWorkLogService workLogService; | ||
| 51 | + @Resource | ||
| 52 | + private PmsWorkItemService workItemService; | ||
| 53 | + | ||
| 54 | + @Resource | ||
| 55 | + private AdminUserApi adminUserApi; | ||
| 56 | + | ||
| 57 | + @PostMapping("/create") | ||
| 58 | + @Operation(summary = "创建工作项工时记录") | ||
| 59 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 60 | + public CommonResult<Long> createWorkItemWorkLog(@Valid @RequestBody PmsWorkItemWorkLogSaveReqVO saveReqVO) { | ||
| 61 | + return success(workLogService.createWorkItemWorkLog(saveReqVO, getLoginUserId())); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + @PutMapping("/update") | ||
| 65 | + @Operation(summary = "更新工作项工时记录") | ||
| 66 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:update')") | ||
| 67 | + public CommonResult<Boolean> updateWorkItemWorkLog(@Valid @RequestBody PmsWorkItemWorkLogSaveReqVO saveReqVO) { | ||
| 68 | + workLogService.updateWorkItemWorkLog(saveReqVO, getLoginUserId()); | ||
| 69 | + return success(true); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + @GetMapping("/get") | ||
| 73 | + @Operation(summary = "获得工作项工时记录") | ||
| 74 | + @Parameter(name = "id", description = "工时记录编号", required = true, example = "1024") | ||
| 75 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 76 | + public CommonResult<PmsWorkItemWorkLogRespVO> getWorkItemWorkLog(@RequestParam("id") Long id) { | ||
| 77 | + PmsWorkItemWorkLogDO workLog = workLogService.getWorkItemWorkLog(id, getLoginUserId()); | ||
| 78 | + PmsWorkItemWorkLogRespVO respVO = BeanUtils.toBean(workLog, PmsWorkItemWorkLogRespVO.class) | ||
| 79 | + .setCreatorUserId(NumberUtils.parseLong(workLog.getCreator())); | ||
| 80 | + fillWorkItemWorkLogRespVOList(Collections.singletonList(respVO)); | ||
| 81 | + return success(respVO); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + @GetMapping("/summary") | ||
| 85 | + @Operation(summary = "获得工作项工时汇总") | ||
| 86 | + @Parameter(name = "workItemId", description = "工作项编号", required = true, example = "1024") | ||
| 87 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 88 | + public CommonResult<PmsWorkItemWorkLogSummaryRespVO> getWorkItemWorkLogSummary( | ||
| 89 | + @RequestParam("workItemId") Long workItemId) { | ||
| 90 | + PmsWorkItemWorkLogSummaryRespVO summary = workLogService.getWorkItemWorkLogSummary(workItemId, getLoginUserId()); | ||
| 91 | + fillWorkItemWorkLogRespVOList(summary.getRecords()); | ||
| 92 | + return success(summary); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + @GetMapping("/project-report") | ||
| 96 | + @Operation(summary = "获得项目工时报表") | ||
| 97 | + @PreAuthorize("@ss.hasPermission('pms:pm:work-item:query')") | ||
| 98 | + public CommonResult<PmsProjectWorkLogReportRespVO> getProjectWorkItemWorkLogReport( | ||
| 99 | + @Valid PmsProjectWorkLogReportReqVO reqVO) { | ||
| 100 | + PmsProjectWorkLogReportRespVO report = workLogService.getProjectWorkItemWorkLogReport( | ||
| 101 | + reqVO, getLoginUserId()); | ||
| 102 | + return success(report); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + // ==================== 拼接 VO ==================== | ||
| 106 | + | ||
| 107 | + private List<PmsWorkItemWorkLogRespVO> fillWorkItemWorkLogRespVOList(List<PmsWorkItemWorkLogRespVO> workLogs) { | ||
| 108 | + if (CollUtil.isEmpty(workLogs)) { | ||
| 109 | + return Collections.emptyList(); | ||
| 110 | + } | ||
| 111 | + // 1. 批量查询创建人和工作项 | ||
| 112 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet( | ||
| 113 | + workLogs, PmsWorkItemWorkLogRespVO::getCreatorUserId)); | ||
| 114 | + Map<Long, PmsWorkItemDO> workItemMap = workItemService.getWorkItemMap( | ||
| 115 | + convertSet(workLogs, PmsWorkItemWorkLogRespVO::getWorkItemId)); | ||
| 116 | + // 2. 拼接创建人和工作项名称 | ||
| 117 | + for (PmsWorkItemWorkLogRespVO workLog : workLogs) { | ||
| 118 | + findAndThen(userMap, workLog.getCreatorUserId(), user -> workLog.setCreatorUserName(user.getNickname())); | ||
| 119 | + findAndThen(workItemMap, workLog.getWorkItemId(), item -> workLog.setWorkItemName(item.getName())); | ||
| 120 | + } | ||
| 121 | + return workLogs; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/activity/PmsWorkItemActivityRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.activity; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.experimental.Accessors; | ||
| 6 | + | ||
| 7 | +import java.time.LocalDateTime; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 工作项动态响应 VO") | ||
| 10 | +@Data | ||
| 11 | +@Accessors(chain = true) | ||
| 12 | +public class PmsWorkItemActivityRespVO { | ||
| 13 | + | ||
| 14 | + @Schema(description = "动态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 15 | + private Long id; | ||
| 16 | + | ||
| 17 | + @Schema(description = "工作项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | ||
| 18 | + private Long workItemId; | ||
| 19 | + | ||
| 20 | + @Schema(description = "操作人用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 21 | + private Long operatorUserId; | ||
| 22 | + | ||
| 23 | + @Schema(description = "操作人姓名", example = "芋道") | ||
| 24 | + private String operatorUserName; | ||
| 25 | + | ||
| 26 | + @Schema(description = "操作人头像") | ||
| 27 | + private String operatorUserAvatar; | ||
| 28 | + | ||
| 29 | + @Schema(description = "动态内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "更新了工作项") | ||
| 30 | + private String content; | ||
| 31 | + | ||
| 32 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 33 | + private LocalDateTime createTime; | ||
| 34 | + | ||
| 35 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/comment/PmsWorkItemCommentRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.comment; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 工作项评论 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsWorkItemCommentRespVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "评论编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "工作项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + private Long workItemId; | ||
| 18 | + | ||
| 19 | + @Schema(description = "评论人用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 20 | + private Long userId; | ||
| 21 | + | ||
| 22 | + @Schema(description = "评论人姓名", example = "芋道源码") | ||
| 23 | + private String userName; | ||
| 24 | + | ||
| 25 | + @Schema(description = "主评论编号", example = "1024") | ||
| 26 | + private Long mainId; | ||
| 27 | + | ||
| 28 | + @Schema(description = "回复对象用户编号", example = "2048") | ||
| 29 | + private Long replyUserId; | ||
| 30 | + | ||
| 31 | + @Schema(description = "回复对象姓名", example = "源码") | ||
| 32 | + private String replyUserName; | ||
| 33 | + | ||
| 34 | + @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 35 | + private String content; | ||
| 36 | + | ||
| 37 | + @Schema(description = "回复列表") | ||
| 38 | + private List<PmsWorkItemCommentRespVO> children; | ||
| 39 | + | ||
| 40 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 41 | + private LocalDateTime createTime; | ||
| 42 | + | ||
| 43 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/comment/PmsWorkItemCommentSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.comment; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 6 | +import jakarta.validation.constraints.Size; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - PMS 工作项评论新增/修改 Request VO") | ||
| 10 | +@Data | ||
| 11 | +public class PmsWorkItemCommentSaveReqVO { | ||
| 12 | + | ||
| 13 | + @Schema(description = "评论编号", example = "1024") | ||
| 14 | + private Long id; | ||
| 15 | + | ||
| 16 | + @Schema(description = "工作项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + @NotNull(message = "工作项编号不能为空") | ||
| 18 | + private Long workItemId; | ||
| 19 | + | ||
| 20 | + @Schema(description = "主评论编号,回复时传入", example = "1024") | ||
| 21 | + private Long mainId; | ||
| 22 | + | ||
| 23 | + @Schema(description = "回复对象用户编号", example = "2048") | ||
| 24 | + private Long replyUserId; | ||
| 25 | + | ||
| 26 | + @Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "已处理") | ||
| 27 | + @NotBlank(message = "评论内容不能为空") | ||
| 28 | + @Size(max = 2000, message = "评论内容不能超过 2000 个字符") | ||
| 29 | + private String content; | ||
| 30 | + | ||
| 31 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/label/PmsWorkItemLabelRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.label; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 工作项标签 Response VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsWorkItemLabelRespVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "标签编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "标签名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "紧急") | ||
| 16 | + private String name; | ||
| 17 | + | ||
| 18 | + @Schema(description = "标签颜色", requiredMode = Schema.RequiredMode.REQUIRED, example = "#409EFF") | ||
| 19 | + private String color; | ||
| 20 | + | ||
| 21 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 22 | + private LocalDateTime createTime; | ||
| 23 | + | ||
| 24 | +} |
yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/label/PmsWorkItemLabelSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.label; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import jakarta.validation.constraints.NotBlank; | ||
| 5 | +import jakarta.validation.constraints.Size; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +@Schema(description = "管理后台 - PMS 工作项标签新增/修改 Request VO") | ||
| 9 | +@Data | ||
| 10 | +public class PmsWorkItemLabelSaveReqVO { | ||
| 11 | + | ||
| 12 | + @Schema(description = "标签编号", example = "1024") | ||
| 13 | + private Long id; | ||
| 14 | + | ||
| 15 | + @Schema(description = "标签名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "紧急") | ||
| 16 | + @NotBlank(message = "标签名称不能为空") | ||
| 17 | + @Size(max = 50, message = "标签名称不能超过 50 个字符") | ||
| 18 | + private String name; | ||
| 19 | + | ||
| 20 | + @Schema(description = "标签颜色", requiredMode = Schema.RequiredMode.REQUIRED, example = "#409EFF") | ||
| 21 | + @NotBlank(message = "标签颜色不能为空") | ||
| 22 | + @Size(max = 20, message = "标签颜色不能超过 20 个字符") | ||
| 23 | + private String color; | ||
| 24 | + | ||
| 25 | +} |