diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/constant/ProductObjectConstants.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/constant/ProductObjectConstants.java index a4cd2a9..5c7bc05 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/constant/ProductObjectConstants.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/constant/ProductObjectConstants.java @@ -23,6 +23,11 @@ public final class ProductObjectConstants { */ public static final String STATUS_PAUSED = "paused"; + /** + * 产品废弃状态。 + */ + public static final String STATUS_ABANDONED = "abandoned"; + /** * 产品自动编码前缀。 */ diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/controller/admin/product/ProductController.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/controller/admin/product/ProductController.java index 28391a6..0f79f06 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/controller/admin/product/ProductController.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/controller/admin/product/ProductController.java @@ -6,6 +6,7 @@ import com.njcn.rdms.framework.common.util.object.BeanUtils; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductContextRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductCreateWithTeamReqVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductDeleteReqVO; +import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductOptionRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductOverviewSummaryRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductPageReqVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductRespVO; @@ -22,6 +23,8 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + import static com.njcn.rdms.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - 产品管理") @@ -82,6 +85,12 @@ public class ProductController { return success(productService.getProductOverviewSummary()); } + @GetMapping("/options") + @Operation(summary = "获取可绑定产品下拉选项") + public CommonResult> getProductOptions() { + return success(productService.getProductOptions()); + } + @PostMapping("/change-status") @Operation(summary = "变更产品状态") public CommonResult changeProductStatus(@Valid @RequestBody ProductStatusActionReqVO reqVO) { diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/controller/admin/product/vo/product/ProductOptionRespVO.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/controller/admin/product/vo/product/ProductOptionRespVO.java new file mode 100644 index 0000000..a6fab93 --- /dev/null +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/controller/admin/product/vo/product/ProductOptionRespVO.java @@ -0,0 +1,21 @@ +package com.njcn.rdms.module.project.controller.admin.product.vo.product; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 产品下拉选项 Response VO") +@Data +public class ProductOptionRespVO { + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "产品编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CNPD2026001") + private String code; + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "灿能管理后台") + private String name; + + @Schema(description = "产品方向字典值", example = "direction_value") + private String directionCode; +} diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/product/ProductMapper.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/product/ProductMapper.java index 66e1a30..889a6a2 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/product/ProductMapper.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/product/ProductMapper.java @@ -48,5 +48,4 @@ public interface ProductMapper extends BaseMapperX { .eq(ProductDO::getId, id) .eq(ProductDO::getStatusCode, statusCode)); } - } diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/framework/attachment/AttachmentValidator.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/framework/attachment/AttachmentValidator.java index ccf4223..9e5269b 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/framework/attachment/AttachmentValidator.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/framework/attachment/AttachmentValidator.java @@ -38,7 +38,9 @@ public final class AttachmentValidator { // 压缩 "zip", "rar", "7z", // 媒体 - "mp4", "mp3" + "mp4", "mp3", + // 其他 + "sql", "xml", "json" ); /** 禁止的扩展名黑名单(即使在白名单也禁,兜底防可执行 / 脚本类)。 */ diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/product/ProductService.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/product/ProductService.java index 4097369..31da1bd 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/product/ProductService.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/product/ProductService.java @@ -4,6 +4,7 @@ import com.njcn.rdms.framework.common.pojo.PageResult; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductContextRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductCreateWithTeamReqVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductDeleteReqVO; +import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductOptionRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductOverviewSummaryRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductPageReqVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductRespVO; @@ -12,6 +13,8 @@ import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductS import com.njcn.rdms.module.project.controller.admin.product.vo.setting.ProductSettingBaseInfoUpdateReqVO; import com.njcn.rdms.module.project.dal.dataobject.product.ProductDO; +import java.util.List; + /** * 产品 Service 接口 */ @@ -89,6 +92,13 @@ public interface ProductService { */ ProductOverviewSummaryRespVO getProductOverviewSummary(); + /** + * 获取可绑定产品下拉选项。 + * + * @return 产品下拉选项 + */ + List getProductOptions(); + /** * 变更产品状态 * diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/product/ProductServiceImpl.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/product/ProductServiceImpl.java index 2ce687d..9b20df7 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/product/ProductServiceImpl.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/product/ProductServiceImpl.java @@ -20,6 +20,7 @@ import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductC import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductContextRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductCreateWithTeamReqVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductDeleteReqVO; +import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductOptionRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductOverviewSummaryRespVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductPageReqVO; import com.njcn.rdms.module.project.controller.admin.product.vo.product.ProductSaveReqVO; @@ -68,6 +69,10 @@ import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil @Service public class ProductServiceImpl implements ProductService { + private static final List PRODUCT_BIND_EXCLUDED_STATUS_CODES = List.of( + ProductObjectConstants.STATUS_PAUSED, + ProductObjectConstants.STATUS_ABANDONED); + @Resource private ProductMapper productMapper; @Resource @@ -455,6 +460,29 @@ public class ProductServiceImpl implements ProductService { return respVO; } + @Override + public List getProductOptions() { + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + ObjectDataScope scope = objectDataScopeService.compute(loginUserId, ProductObjectConstants.OBJECT_TYPE); + if (scope.getState() == ObjectDataScope.State.EMPTY) { + return Collections.emptyList(); + } + LambdaQueryWrapperX wrapper = new LambdaQueryWrapperX<>(); + wrapper.notIn(ProductDO::getStatusCode, PRODUCT_BIND_EXCLUDED_STATUS_CODES); + wrapper.orderByDesc(ProductDO::getCreateTime); + applyProductScopeFilter(wrapper, scope); + return productMapper.selectList(wrapper).stream() + .map(product -> { + ProductOptionRespVO respVO = new ProductOptionRespVO(); + respVO.setId(product.getId()); + respVO.setCode(product.getCode()); + respVO.setName(product.getName()); + respVO.setDirectionCode(product.getDirectionCode()); + return respVO; + }) + .toList(); + } + /** * 按 scope 算出 (statusCode, countValue) 行集,喂给 {@link #buildProductStatusCounts}。 * EMPTY 直接空集;ALL 走原全表 GROUP BY SQL;ID_LIST 用 wrapper 取 status_code,Java 端 group + count。 @@ -469,6 +497,24 @@ public class ProductServiceImpl implements ProductService { // ID_LIST LambdaQueryWrapperX wrapper = new LambdaQueryWrapperX<>(); wrapper.select(ProductDO::getStatusCode); + applyProductScopeFilter(wrapper, scope); + return productMapper.selectList(wrapper).stream() + .filter(p -> p.getStatusCode() != null) + .collect(Collectors.groupingBy(ProductDO::getStatusCode, Collectors.counting())) + .entrySet().stream() + .map(e -> { + Map row = new HashMap<>(); + row.put("statusCode", e.getKey()); + row.put("countValue", e.getValue()); + return row; + }) + .collect(Collectors.toList()); + } + + private void applyProductScopeFilter(LambdaQueryWrapperX wrapper, ObjectDataScope scope) { + if (scope.getState() != ObjectDataScope.State.ID_LIST) { + return; + } Set ids = scope.getIds(); Set dcs = scope.getDirectionCodes(); wrapper.and(w -> { @@ -484,17 +530,6 @@ public class ProductServiceImpl implements ProductService { w.in(ProductDO::getDirectionCode, dcs); } }); - return productMapper.selectList(wrapper).stream() - .filter(p -> p.getStatusCode() != null) - .collect(Collectors.groupingBy(ProductDO::getStatusCode, Collectors.counting())) - .entrySet().stream() - .map(e -> { - Map row = new HashMap<>(); - row.put("statusCode", e.getKey()); - row.put("countValue", e.getValue()); - return row; - }) - .collect(Collectors.toList()); } @Override diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/common/WorkReportCommonService.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/common/WorkReportCommonService.java index 23a2882..05bd48a 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/common/WorkReportCommonService.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/common/WorkReportCommonService.java @@ -185,7 +185,7 @@ public class WorkReportCommonService { WeeklyReportRespVO respVO = latestDraft; respVO.setIsBusinessTrip(Boolean.TRUE.equals(reqVO.getIsBusinessTrip())); respVO.setTravelSegments(BeanUtils.toBean(defaultList(reqVO.getTravelSegments()), WeeklyReportTravelSegmentRespVO.class)); - respVO.setReviewItems(mergeReviewItems(reqVO.getReviewItems(), latestDraft.getReviewItems())); + respVO.setReviewItems(mergeWeeklyReviewItems(reqVO.getReviewItems(), latestDraft.getReviewItems())); respVO.setPlanItems(mergePlanItems(reqVO.getPlanItems(), latestDraft.getPlanItems())); respVO.setTotalTravelDays(Boolean.TRUE.equals(reqVO.getIsBusinessTrip()) ? defaultIfNull(sumTravelDays(reqVO.getTravelSegments())) @@ -1132,6 +1132,45 @@ public class WorkReportCommonService { return merged; } + private List mergeWeeklyReviewItems(List currentItems, + List latestItems) { + List merged = BeanUtils.toBean(defaultList(currentItems), + PersonalReportReviewItemRespVO.class); + Map latestItemMap = defaultList(latestItems).stream() + .filter(Objects::nonNull) + .filter(item -> StringUtils.hasText(item.getItemTitle())) + .collect(Collectors.toMap(item -> normalizeMergeText(item.getItemTitle()), + item -> item, (left, right) -> right, LinkedHashMap::new)); + Set existingKeys = new LinkedHashSet<>(); + for (PersonalReportReviewItemRespVO item : merged) { + String key = normalizeMergeText(item.getItemTitle()); + if (!StringUtils.hasText(key)) { + continue; + } + PersonalReportReviewItemRespVO latestItem = latestItemMap.get(key); + if (latestItem != null) { + item.setWorkHours(latestItem.getWorkHours()); + item.setContentText(latestItem.getContentText()); + item.setContentJson(latestItem.getContentJson()); + } + existingKeys.add(key); + } + for (PersonalReportReviewItemRespVO item : defaultList(latestItems)) { + String key = normalizeMergeText(item.getItemTitle()); + if (StringUtils.hasText(key) && existingKeys.contains(key)) { + continue; + } + merged.add(BeanUtils.toBean(item, PersonalReportReviewItemRespVO.class)); + if (StringUtils.hasText(key)) { + existingKeys.add(key); + } + } + for (int i = 0; i < merged.size(); i++) { + merged.get(i).setItemNumber(i + 1); + } + return merged; + } + private List mergePlanItems(List currentItems, List latestItems) { List merged = BeanUtils.toBean(defaultList(currentItems), diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthLoginReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthLoginReqVO.java index 4818202..623d640 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthLoginReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthLoginReqVO.java @@ -25,7 +25,7 @@ public class AuthLoginReqVO extends CaptchaVerificationReqVO { @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao") @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 4, max = 30, message = "密码长度为 4-30 位") private String password; } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java index 6b74a10..1a985b1 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java @@ -38,6 +38,6 @@ public class AuthRegisterReqVO extends CaptchaVerificationReqVO { @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 4, max = 30, message = "密码长度为 4-30 位") private String password; } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java index 9cfdded..0ec1246 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/profile/UserProfileUpdatePasswordReqVO.java @@ -12,12 +12,12 @@ public class UserProfileUpdatePasswordReqVO { @Schema(description = "旧密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotEmpty(message = "旧密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 4, max = 30, message = "密码长度为 4-30 位") private String oldPassword; @Schema(description = "新密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "654321") @NotEmpty(message = "新密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 4, max = 30, message = "密码长度为 4-30 位") private String newPassword; } diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserSaveReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserSaveReqVO.java index 721eadb..ec560b9 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserSaveReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserSaveReqVO.java @@ -89,7 +89,7 @@ public class UserSaveReqVO { // ========== 仅【创建】时,需要传递的字段 ========== @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 4, max = 30, message = "密码长度为 4-30 位") private String password; @AssertTrue(message = "密码不能为空") diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java index 121804e..0f32dc2 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/user/vo/user/UserUpdatePasswordReqVO.java @@ -17,7 +17,7 @@ public class UserUpdatePasswordReqVO { @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + @Length(min = 4, max = 30, message = "密码长度为 4-30 位") private String password; }