src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java
@@ -9,4 +9,8 @@ private String approveAction; private String approveComment; private String createTimeEnd; private String createTimeStart; } src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java
@@ -4,6 +4,7 @@ import com.ruoyi.approve.bean.dto.ApprovalInstanceDto; import com.ruoyi.approve.bean.vo.ApprovalInstanceVo; import com.ruoyi.approve.service.ApprovalInstanceService; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.R; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -24,7 +25,7 @@ @RequestMapping("/approvalInstance") @Tag(name = "审æ¹å®ä¾è¡¨") @AllArgsConstructor public class ApprovalInstanceController { public class ApprovalInstanceController extends BaseController { private final ApprovalInstanceService approvalInstanceService; @GetMapping("/listPage") src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java
@@ -1,5 +1,6 @@ package com.ruoyi.approve.controller; import com.ruoyi.framework.web.controller.BaseController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -13,6 +14,6 @@ */ @RestController @RequestMapping("/approvalInstanceNode") public class ApprovalInstanceNodeController { public class ApprovalInstanceNodeController extends BaseController { } src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java
@@ -1,11 +1,13 @@ package com.ruoyi.approve.pojo; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; import java.time.LocalDateTime; @@ -118,6 +120,8 @@ */ @Schema(description ="å建æ¶é´") @TableField(fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; /** src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
@@ -10,23 +10,29 @@ import com.ruoyi.approve.bean.dto.ApprovalInstanceDto; import com.ruoyi.approve.bean.vo.ApprovalInstanceVo; import com.ruoyi.approve.mapper.ApprovalInstanceMapper; import com.ruoyi.approve.mapper.ApprovalTemplateMapper; import com.ruoyi.approve.pojo.*; import com.ruoyi.approve.service.*; import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService; import com.ruoyi.common.enums.*; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.framework.security.LoginUser; import com.ruoyi.framework.web.domain.R; import com.ruoyi.procurementrecord.utils.StockUtils; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.project.system.mapper.SysUserDeptMapper; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.project.system.service.ISysNoticeService; import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; import com.ruoyi.purchase.pojo.PurchaseLedger; import com.ruoyi.quality.mapper.QualityInspectMapper; import com.ruoyi.quality.mapper.QualityInspectParamMapper; import com.ruoyi.quality.mapper.QualityTestStandardMapper; import com.ruoyi.quality.mapper.QualityTestStandardParamMapper; import com.ruoyi.quality.utils.QualityInspectHelper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.mapper.SalesQuotationMapper; @@ -54,6 +60,9 @@ @RequiredArgsConstructor public class ApprovalInstanceServiceImpl extends ServiceImpl<ApprovalInstanceMapper, ApprovalInstance> implements ApprovalInstanceService { private static final String ENTERPRISE_NEWS_STATUS_PUBLISHED = "PUBLISHED"; private static final String ENTERPRISE_NEWS_STATUS_REJECTED = "REJECTED"; private final ApprovalInstanceMapper approvalInstanceMapper; private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils; private final ApprovalInstanceNodeService approvalInstanceNodeService; @@ -65,14 +74,15 @@ private final PurchaseLedgerMapper purchaseLedgerMapper; private final SalesLedgerProductMapper salesLedgerProductMapper; private final StockUtils stockUtils; private final QualityInspectMapper qualityInspectMapper; private final QualityTestStandardMapper qualityTestStandardMapper; private final QualityTestStandardParamMapper qualityTestStandardParamMapper; private final QualityInspectParamMapper qualityInspectParamMapper; private final SalesQuotationMapper salesQuotationMapper; private final ShippingInfoMapper shippingInfoMapper; private final ApprovalTemplateMapper approvalTemplateMapper; private final QualityInspectHelper qualityInspectHelper; private final EnterpriseNewsService enterpriseNewsService; private final EnterpriseNewsScopeDeptService enterpriseNewsScopeDeptService; private final EnterpriseNewsScopeUserService enterpriseNewsScopeUserService; private final SysUserMapper sysUserMapper; private final SysUserDeptMapper sysUserDeptMapper; private final SysDeptMapper sysDeptMapper; @Override public R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto) { @@ -331,6 +341,28 @@ } if (TypeEnums.SHIPPING_APPROVAL.getCode().equals(businessType)) { handleShippingApprovalFinished(instance, status); return; } if (TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode().equals(businessType)) { handleNewsApprovalFinished(instance, status); } } private void handleNewsApprovalFinished(ApprovalInstance instance, String status) { if (instance == null || instance.getBusinessId() == null) { return; } EnterpriseNews enterpriseNews = new EnterpriseNews(); enterpriseNews.setId(instance.getBusinessId()); if ("APPROVED".equals(status)) { enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_PUBLISHED); enterpriseNewsService.updateById(enterpriseNews); sendEnterpriseNewsNotice(instance.getBusinessId()); return; } if ("REJECTED".equals(status)) { enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_REJECTED); enterpriseNewsService.updateById(enterpriseNews); } } @@ -474,6 +506,82 @@ sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath); } private void sendEnterpriseNewsNotice(Long newsId) { EnterpriseNews enterpriseNews = enterpriseNewsService.getById(newsId); if (enterpriseNews == null) { return; } List<Long> userIds = getEnterpriseNewsNoticeUserIds(enterpriseNews); if (userIds == null || userIds.isEmpty()) { return; } String title = "ä¼ä¸æ°é»"; String message = "æ¨ææ°çä¼ä¸æ°é»ã" + enterpriseNews.getTitle() + "ãè¯·åæ¶æ¥é "; String jumpPath = "/enterpriseNews?id=" + newsId; sysNoticeService.simpleNoticeByUser(title, message, userIds, jumpPath); } private List<Long> getEnterpriseNewsNoticeUserIds(EnterpriseNews enterpriseNews) { if (enterpriseNews == null || !org.springframework.util.StringUtils.hasText(enterpriseNews.getReadScope())) { return Collections.emptyList(); } String readScope = enterpriseNews.getReadScope().trim(); if ("all".equals(readScope)) { return sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>() .select(SysUser::getUserId) .eq(SysUser::getDelFlag, "0")) .stream() .map(SysUser::getUserId) .filter(id -> id != null && id > 0) .distinct() .collect(Collectors.toList()); } if ("dept".equals(readScope)) { List<Long> deptIds = enterpriseNewsScopeDeptService.list( new LambdaQueryWrapper<EnterpriseNewsScopeDept>() .eq(EnterpriseNewsScopeDept::getNewsId, enterpriseNews.getId())) .stream() .map(EnterpriseNewsScopeDept::getDeptId) .filter(id -> id != null && id > 0) .distinct() .collect(Collectors.toList()); if (deptIds.isEmpty()) { return Collections.emptyList(); } return sysUserDeptMapper.selectDistinctUserIdsByDeptIds(collectDeptIdsWithChildren(deptIds)); } if ("custom".equals(readScope)) { return enterpriseNewsScopeUserService.list( new LambdaQueryWrapper<EnterpriseNewsScopeUser>() .eq(EnterpriseNewsScopeUser::getNewsId, enterpriseNews.getId())) .stream() .map(EnterpriseNewsScopeUser::getUserId) .filter(id -> id != null && id > 0) .distinct() .collect(Collectors.toList()); } return Collections.emptyList(); } private List<Long> collectDeptIdsWithChildren(List<Long> deptIds) { Set<Long> allDeptIds = new LinkedHashSet<>(); for (Long deptId : deptIds) { if (deptId == null) { continue; } allDeptIds.add(deptId); List<SysDept> children = sysDeptMapper.selectChildrenDeptById(deptId); if (children != null && !children.isEmpty()) { for (SysDept child : children) { if (child != null && child.getDeptId() != null) { allDeptIds.add(child.getDeptId()); } } } } return new ArrayList<>(allDeptIds); } private void closePendingTasks(Long instanceId, Long nodeId) { LambdaUpdateWrapper<ApprovalTask> updateWrapper = Wrappers.lambdaUpdate(); updateWrapper.eq(ApprovalTask::getInstanceId, instanceId) src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,55 @@ package com.ruoyi.collaborativeApproval.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService; import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo; import com.ruoyi.framework.web.domain.R; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; /** * <p> * ä¼ä¸æ°é»è¡¨ å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:50:59 */ @RestController @RequestMapping("/enterpriseNews") @Tag(name = "ä¼ä¸æ°é»è¡¨") @AllArgsConstructor public class EnterpriseNewsController { private final EnterpriseNewsService enterpriseNewsService; @Operation(summary = "å页æ¥è¯¢") @GetMapping("/listPage") public R listPage(Page<EnterpriseNewsVo> page , EnterpriseNewsDto enterpriseNewsDto) { return R.ok(enterpriseNewsService.listPage(page, enterpriseNewsDto)); } @PostMapping("/save") @Operation(summary = "ä¿å") public R save(@RequestBody EnterpriseNewsDto enterpriseNewsDto) { return R.ok(enterpriseNewsService.add(enterpriseNewsDto)); } @PutMapping("/update") @Operation(summary = "æ´æ°") public R update(@RequestBody EnterpriseNewsDto enterpriseNewsDto) { return R.ok(enterpriseNewsService.updateEnterpriseNewsDto(enterpriseNewsDto)); } @DeleteMapping("/delete") @Operation(summary = "å é¤") public R delete(@RequestBody List<Long> ids) { return R.ok(enterpriseNewsService.delete(ids)); } } src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.collaborativeApproval.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * <p> * ä¼ä¸æ°é»é 读èå´é¨é¨è¡¨ å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:12 */ @RestController @RequestMapping("/enterpriseNewsScopeDept") public class EnterpriseNewsScopeDeptController { } src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.collaborativeApproval.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * <p> * ä¼ä¸æ°é»é 读èå´ç¨æ·è¡¨ å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:23 */ @RestController @RequestMapping("/enterpriseNewsScopeUser") public class EnterpriseNewsScopeUserController { } src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,22 @@ package com.ruoyi.collaborativeApproval.dto; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews; import lombok.Data; import java.util.List; @Data public class EnterpriseNewsDto extends EnterpriseNews { private String createUserName; private List<Long> deptIds; private List<Long> userIds; private Long templateId; private String templateName; private String createTimeStart; private String createTimeEnd; } src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,24 @@ package com.ruoyi.collaborativeApproval.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews; import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * <p> * ä¼ä¸æ°é»è¡¨ Mapper æ¥å£ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:50:59 */ @Mapper public interface EnterpriseNewsMapper extends BaseMapper<EnterpriseNews> { IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page,@Param("enterpriseNewsDto") EnterpriseNewsDto enterpriseNewsDto); } src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.collaborativeApproval.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept; import org.apache.ibatis.annotations.Mapper; /** * <p> * ä¼ä¸æ°é»é 读èå´é¨é¨è¡¨ Mapper æ¥å£ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:12 */ @Mapper public interface EnterpriseNewsScopeDeptMapper extends BaseMapper<EnterpriseNewsScopeDept> { } src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.collaborativeApproval.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser; import org.apache.ibatis.annotations.Mapper; /** * <p> * ä¼ä¸æ°é»é 读èå´ç¨æ·è¡¨ Mapper æ¥å£ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:23 */ @Mapper public interface EnterpriseNewsScopeUserMapper extends BaseMapper<EnterpriseNewsScopeUser> { } src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,88 @@ package com.ruoyi.collaborativeApproval.pojo; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; import java.time.LocalDateTime; /** * ä¼ä¸æ°é»è¡¨ * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:50:59 */ @Getter @Setter @ToString @TableName("enterprise_news") @ApiModel(value = "EnterpriseNews对象", description = "ä¼ä¸æ°é»è¡¨") public class EnterpriseNews implements Serializable { private static final long serialVersionUID = 1L; @Schema(description = "ç¼å· ID") @TableId(value = "id", type = IdType.AUTO) private Long id; @Schema(description = "æ é¢ Title") private String title; @Schema(description = "æè¦ Summary") private String summary; @Schema(description = "æ£æ Content") private String content; @Schema(description = "åç±» Category") private String category; @Schema(description = "é 读èå´ Read scope: all å ¨å, dept é¨é¨, custom èªå®ä¹") private String readScope; @Schema(description = "æ¯å¦å¿ 读 Required flag: 0 å¦, 1 æ¯") private Byte isRequired; @Schema(description = "ç¶æ Status: DRAFT è稿, PENDING å¾ å®¡æ¹, PUBLISHED å·²åå¸, REJECTED 驳å, OFFLINE å·²ä¸çº¿") private String status; @Schema(description = "åºè¯»äººæ° Required read count") private Integer requiredReadCount; @Schema(description = "å·²è¯»äººæ° Read count") private Integer readCount; @Schema(description = "å建人 Create user") @TableField(fill = FieldFill.INSERT) private Long createUser; @Schema(description = "å建æ¶é´ Create time") @TableField(fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss", iso = DateTimeFormat.ISO.DATE_TIME) private LocalDateTime createTime; @Schema(description = "æ´æ°äºº Update user") @TableField(fill = FieldFill.INSERT_UPDATE) private Long updateUser; @Schema(description = "æ´æ°æ¶é´ Update time") @TableField(fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss", iso = DateTimeFormat.ISO.DATE_TIME) private LocalDateTime updateTime; @Schema(description = "é¨é¨ID Dept ID") @TableField(fill = FieldFill.INSERT) private Long deptId; } src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,59 @@ package com.ruoyi.collaborativeApproval.pojo; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.io.Serializable; import java.time.LocalDateTime; /** * <p> * ä¼ä¸æ°é»é 读èå´é¨é¨è¡¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:12 */ @Getter @Setter @ToString @TableName("enterprise_news_scope_dept") @ApiModel(value = "EnterpriseNewsScopeDept对象", description = "ä¼ä¸æ°é»é 读èå´é¨é¨è¡¨") public class EnterpriseNewsScopeDept implements Serializable { private static final long serialVersionUID = 1L; /** * ç¼å· */ @ApiModelProperty("ç¼å·") @TableId(value = "id", type = IdType.AUTO) private Long id; /** * ä¼ä¸æ°é»ID */ @ApiModelProperty("ä¼ä¸æ°é»ID") private Long newsId; /** * é¨é¨ID */ @ApiModelProperty("é¨é¨ID") private Long deptId; /** * å建æ¶é´ */ @ApiModelProperty("å建æ¶é´") @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; } src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,59 @@ package com.ruoyi.collaborativeApproval.pojo; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.io.Serializable; import java.time.LocalDateTime; /** * <p> * ä¼ä¸æ°é»é 读èå´ç¨æ·è¡¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:23 */ @Getter @Setter @ToString @TableName("enterprise_news_scope_user") @ApiModel(value = "EnterpriseNewsScopeUser对象", description = "ä¼ä¸æ°é»é 读èå´ç¨æ·è¡¨") public class EnterpriseNewsScopeUser implements Serializable { private static final long serialVersionUID = 1L; /** * ç¼å· */ @ApiModelProperty("ç¼å·") @TableId(value = "id", type = IdType.AUTO) private Long id; /** * ä¼ä¸æ°é»ID */ @ApiModelProperty("ä¼ä¸æ°é»ID") private Long newsId; /** * ç¨æ·ID */ @ApiModelProperty("ç¨æ·ID") private Long userId; /** * å建æ¶é´ */ @ApiModelProperty("å建æ¶é´") @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; } src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.collaborativeApproval.service; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept; import com.baomidou.mybatisplus.extension.service.IService; /** * <p> * ä¼ä¸æ°é»é 读èå´é¨é¨è¡¨ æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:12 */ public interface EnterpriseNewsScopeDeptService extends IService<EnterpriseNewsScopeDept> { } src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.collaborativeApproval.service; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser; import com.baomidou.mybatisplus.extension.service.IService; /** * <p> * ä¼ä¸æ°é»é 读èå´ç¨æ·è¡¨ æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:23 */ public interface EnterpriseNewsScopeUserService extends IService<EnterpriseNewsScopeUser> { } src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,29 @@ package com.ruoyi.collaborativeApproval.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo; import java.util.List; /** * <p> * ä¼ä¸æ°é»è¡¨ æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:50:59 */ public interface EnterpriseNewsService extends IService<EnterpriseNews> { IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page, EnterpriseNewsDto enterpriseNewsDto); Boolean add(EnterpriseNewsDto enterpriseNewsDto); Boolean updateEnterpriseNewsDto(EnterpriseNewsDto enterpriseNewsDto); Boolean delete(List<Long> ids); } src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ package com.ruoyi.collaborativeApproval.service.impl; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept; import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** * <p> * ä¼ä¸æ°é»é 读èå´é¨é¨è¡¨ æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:12 */ @Service public class EnterpriseNewsScopeDeptServiceImpl extends ServiceImpl<EnterpriseNewsScopeDeptMapper, EnterpriseNewsScopeDept> implements EnterpriseNewsScopeDeptService { } src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ package com.ruoyi.collaborativeApproval.service.impl; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser; import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** * <p> * ä¼ä¸æ°é»é 读èå´ç¨æ·è¡¨ æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:51:23 */ @Service public class EnterpriseNewsScopeUserServiceImpl extends ServiceImpl<EnterpriseNewsScopeUserMapper, EnterpriseNewsScopeUser> implements EnterpriseNewsScopeUserService { } src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,378 @@ package com.ruoyi.collaborativeApproval.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.approve.mapper.ApprovalInstanceMapper; import com.ruoyi.approve.mapper.ApprovalTemplateMapper; import com.ruoyi.approve.pojo.ApprovalInstance; import com.ruoyi.approve.pojo.ApprovalTask; import com.ruoyi.approve.pojo.ApprovalTemplate; import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils; import com.ruoyi.collaborativeApproval.dto.EnterpriseNewsDto; import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeDeptService; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsScopeUserService; import com.ruoyi.collaborativeApproval.service.EnterpriseNewsService; import com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo; import com.ruoyi.common.enums.TypeEnums; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.project.system.mapper.SysUserDeptMapper; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.project.system.service.ISysNoticeService; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * ä¼ä¸æ°é»è¡¨æå¡å®ç°ç±» * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-05-20 11:50:59 */ @Service @RequiredArgsConstructor public class EnterpriseNewsServiceImpl extends ServiceImpl<EnterpriseNewsMapper, EnterpriseNews> implements EnterpriseNewsService { private static final String READ_SCOPE_ALL = "all"; private static final String READ_SCOPE_DEPT = "dept"; private static final String READ_SCOPE_CUSTOM = "custom"; private static final String STATUS_DRAFT = "DRAFT"; private static final String STATUS_PENDING = "PENDING"; private static final String STATUS_PUBLISHED = "PUBLISHED"; private static final String STATUS_REJECTED = "REJECTED"; private static final String STATUS_OFFLINE = "OFFLINE"; private final EnterpriseNewsMapper enterpriseNewsMapper; private final EnterpriseNewsScopeDeptService enterpriseNewsScopeDeptService; private final EnterpriseNewsScopeUserService enterpriseNewsScopeUserService; private final SysUserMapper sysUserMapper; private final SysDeptMapper sysDeptMapper; private final SysUserDeptMapper sysUserDeptMapper; private final ApprovalInstanceMapper approvalInstanceMapper; private final ApprovalTemplateMapper approvalTemplateMapper; private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils; private final ISysNoticeService sysNoticeService; @Override public IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page, EnterpriseNewsDto enterpriseNewsDto) { return enterpriseNewsMapper.listPage(page, enterpriseNewsDto); } @Override @Transactional(rollbackFor = Exception.class) public Boolean add(EnterpriseNewsDto enterpriseNewsDto) { validateForSave(enterpriseNewsDto); String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope()); List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds()); List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds()); EnterpriseNews enterpriseNews = new EnterpriseNews(); BeanUtils.copyProperties(enterpriseNewsDto, enterpriseNews); enterpriseNews.setReadScope(readScope); enterpriseNews.setIsRequired(enterpriseNewsDto.getIsRequired() == null ? (byte) 0 : enterpriseNewsDto.getIsRequired()); enterpriseNews.setStatus(normalizeStatus(enterpriseNewsDto.getStatus(), STATUS_DRAFT)); enterpriseNews.setReadCount(0); enterpriseNews.setRequiredReadCount(calculateRequiredReadCount(readScope, deptIds, userIds)); Long[] loginDeptIds = SecurityUtils.getDeptId(); if (StringUtils.isNotEmpty(loginDeptIds)) { enterpriseNews.setDeptId(loginDeptIds[0]); } if (!save(enterpriseNews) || enterpriseNews.getId() == null) { throw new ServiceException("æ°å¢ä¼ä¸æ°é»å¤±è´¥"); } saveReadScopeRelations(enterpriseNews.getId(), readScope, deptIds, userIds); if (STATUS_PENDING.equals(enterpriseNews.getStatus())) { startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto); } return true; } @Override @Transactional(rollbackFor = Exception.class) public Boolean updateEnterpriseNewsDto(EnterpriseNewsDto enterpriseNewsDto) { if (enterpriseNewsDto == null || enterpriseNewsDto.getId() == null) { throw new ServiceException("ä¼ä¸æ°é»IDä¸è½ä¸ºç©º"); } EnterpriseNews oldEnterpriseNews = getById(enterpriseNewsDto.getId()); if (oldEnterpriseNews == null) { throw new ServiceException("ä¼ä¸æ°é»ä¸åå¨"); } if (!STATUS_DRAFT.equals(oldEnterpriseNews.getStatus()) && !STATUS_REJECTED.equals(oldEnterpriseNews.getStatus())) { throw new ServiceException("å¾ å®¡æ¹æå·²åå¸çä¼ä¸æ°é»ä¸å 许修æ¹"); } validateForSave(enterpriseNewsDto); String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope()); List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds()); List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds()); EnterpriseNews enterpriseNews = new EnterpriseNews(); BeanUtils.copyProperties(enterpriseNewsDto, enterpriseNews); enterpriseNews.setReadScope(readScope); enterpriseNews.setIsRequired(enterpriseNewsDto.getIsRequired() == null ? oldEnterpriseNews.getIsRequired() : enterpriseNewsDto.getIsRequired()); enterpriseNews.setStatus(normalizeStatus(enterpriseNewsDto.getStatus(), oldEnterpriseNews.getStatus())); enterpriseNews.setReadCount(oldEnterpriseNews.getReadCount()); enterpriseNews.setRequiredReadCount(calculateRequiredReadCount(readScope, deptIds, userIds)); enterpriseNews.setCreateUser(oldEnterpriseNews.getCreateUser()); enterpriseNews.setCreateTime(oldEnterpriseNews.getCreateTime()); enterpriseNews.setDeptId(oldEnterpriseNews.getDeptId()); if (!updateById(enterpriseNews)) { throw new ServiceException("ä¿®æ¹ä¼ä¸æ°é»å¤±è´¥"); } clearReadScopeRelations(enterpriseNews.getId()); saveReadScopeRelations(enterpriseNews.getId(), readScope, deptIds, userIds); if (STATUS_PENDING.equals(enterpriseNews.getStatus())) { startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto); } return true; } @Override public Boolean delete(List<Long> ids) { if (ids == null || ids.isEmpty()) { return false; } if (!removeByIds(ids)) { throw new ServiceException("å é¤ä¼ä¸æ°é»å¤±è´¥"); } ids.forEach(this::clearReadScopeRelations); return true; } private void validateForSave(EnterpriseNewsDto enterpriseNewsDto) { if (enterpriseNewsDto == null) { throw new ServiceException("ä¼ä¸æ°é»æ°æ®ä¸è½ä¸ºç©º"); } if (StringUtils.isEmpty(enterpriseNewsDto.getTitle())) { throw new ServiceException("æ é¢ä¸è½ä¸ºç©º"); } if (StringUtils.isEmpty(enterpriseNewsDto.getContent())) { throw new ServiceException("æ£æä¸è½ä¸ºç©º"); } normalizeStatus(enterpriseNewsDto.getStatus(), STATUS_DRAFT); String readScope = normalizeReadScope(enterpriseNewsDto.getReadScope()); List<Long> deptIds = distinctIds(enterpriseNewsDto.getDeptIds()); List<Long> userIds = distinctIds(enterpriseNewsDto.getUserIds()); if (READ_SCOPE_DEPT.equals(readScope) && StringUtils.isEmpty(deptIds)) { throw new ServiceException("è¯·éæ©é 读èå´é¨é¨"); } if (READ_SCOPE_CUSTOM.equals(readScope) && StringUtils.isEmpty(userIds)) { throw new ServiceException("è¯·éæ©èªå®ä¹é 读人å"); } validateDeptIds(deptIds); validateUserIds(userIds); } private String normalizeReadScope(String readScope) { String normalized = StringUtils.isEmpty(readScope) ? READ_SCOPE_ALL : readScope.trim(); if (!READ_SCOPE_ALL.equals(normalized) && !READ_SCOPE_DEPT.equals(normalized) && !READ_SCOPE_CUSTOM.equals(normalized)) { throw new ServiceException("é 读èå´ä¸åæ³"); } return normalized; } private String normalizeStatus(String status, String defaultStatus) { String normalized = StringUtils.isEmpty(status) ? defaultStatus : status.trim().toUpperCase(); if (!STATUS_DRAFT.equals(normalized) && !STATUS_PENDING.equals(normalized) && !STATUS_PUBLISHED.equals(normalized) && !STATUS_REJECTED.equals(normalized) && !STATUS_OFFLINE.equals(normalized)) { throw new ServiceException("ä¼ä¸æ°é»ç¶æä¸åæ³"); } return normalized; } private void validateDeptIds(List<Long> deptIds) { if (StringUtils.isEmpty(deptIds)) { return; } for (Long deptId : deptIds) { SysDept sysDept = sysDeptMapper.selectDeptById(deptId); if (deptId == null || sysDept == null) { throw new ServiceException("é 读èå´é¨é¨ä¸åå¨"); } } } private void validateUserIds(List<Long> userIds) { if (StringUtils.isEmpty(userIds)) { return; } List<SysUser> users = sysUserMapper.selectUsersByIds(userIds); if (users.size() != userIds.size()) { throw new ServiceException("èªå®ä¹é 读人åå 嫿 æç¨æ·"); } } private Integer calculateRequiredReadCount(String readScope, List<Long> deptIds, List<Long> userIds) { if (READ_SCOPE_ALL.equals(readScope)) { Long count = sysUserMapper.selectCount(new LambdaQueryWrapper<SysUser>() .eq(SysUser::getDelFlag, "0")); return count == null ? 0 : count.intValue(); } if (READ_SCOPE_DEPT.equals(readScope)) { List<Long> allDeptIds = collectDeptIdsWithChildren(deptIds); if (StringUtils.isEmpty(allDeptIds)) { return 0; } Long count = sysUserDeptMapper.countDistinctUserIdsByDeptIds(allDeptIds); return count == null ? 0 : count.intValue(); } return userIds.size(); } private List<Long> collectDeptIdsWithChildren(List<Long> deptIds) { Set<Long> allDeptIds = new LinkedHashSet<>(); for (Long deptId : deptIds) { if (deptId == null) { continue; } allDeptIds.add(deptId); List<SysDept> children = sysDeptMapper.selectChildrenDeptById(deptId); if (StringUtils.isNotEmpty(children)) { for (SysDept child : children) { allDeptIds.add(child.getDeptId()); } } } return new ArrayList<>(allDeptIds); } private void saveReadScopeRelations(Long newsId, String readScope, List<Long> deptIds, List<Long> userIds) { if (READ_SCOPE_DEPT.equals(readScope)) { List<EnterpriseNewsScopeDept> scopeDeptList = new ArrayList<>(); for (Long deptId : deptIds) { EnterpriseNewsScopeDept scopeDept = new EnterpriseNewsScopeDept(); scopeDept.setNewsId(newsId); scopeDept.setDeptId(deptId); scopeDeptList.add(scopeDept); } if (StringUtils.isNotEmpty(scopeDeptList)) { enterpriseNewsScopeDeptService.saveBatch(scopeDeptList); } return; } if (READ_SCOPE_CUSTOM.equals(readScope)) { List<EnterpriseNewsScopeUser> scopeUserList = new ArrayList<>(); for (Long userId : userIds) { EnterpriseNewsScopeUser scopeUser = new EnterpriseNewsScopeUser(); scopeUser.setNewsId(newsId); scopeUser.setUserId(userId); scopeUserList.add(scopeUser); } if (StringUtils.isNotEmpty(scopeUserList)) { enterpriseNewsScopeUserService.saveBatch(scopeUserList); } } } private void clearReadScopeRelations(Long newsId) { enterpriseNewsScopeDeptService.remove(new LambdaQueryWrapper<EnterpriseNewsScopeDept>() .eq(EnterpriseNewsScopeDept::getNewsId, newsId)); enterpriseNewsScopeUserService.remove(new LambdaQueryWrapper<EnterpriseNewsScopeUser>() .eq(EnterpriseNewsScopeUser::getNewsId, newsId)); } private List<Long> distinctIds(List<Long> ids) { if (StringUtils.isEmpty(ids)) { return new ArrayList<>(); } Set<Long> distinctSet = new LinkedHashSet<>(); for (Long id : ids) { if (id != null) { distinctSet.add(id); } } return new ArrayList<>(distinctSet); } private void startEnterpriseNewsApproval(EnterpriseNews enterpriseNews, EnterpriseNewsDto enterpriseNewsDto) { if (enterpriseNewsDto.getTemplateId() == null) { throw new ServiceException("å®¡æ¹æ¨¡æ¿ä¸è½ä¸ºç©º"); } String templateName = enterpriseNewsDto.getTemplateName(); if (StringUtils.isEmpty(templateName)) { ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectById(enterpriseNewsDto.getTemplateId()); if (approvalTemplate == null) { throw new ServiceException("å®¡æ¹æ¨¡æ¿ä¸åå¨"); } templateName = approvalTemplate.getTemplateName(); } ApprovalInstance approvalInstance = new ApprovalInstance(); approvalInstance.setInstanceNo(OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no")); approvalInstance.setTemplateId(enterpriseNewsDto.getTemplateId()); approvalInstance.setTemplateName(templateName); approvalInstance.setBusinessId(enterpriseNews.getId()); approvalInstance.setBusinessType(TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode()); approvalInstance.setTitle(enterpriseNews.getTitle()); approvalInstance.setStatus("PENDING"); approvalInstance.setCurrentLevel(1); approvalInstance.setApplicantId(SecurityUtils.getUserId()); approvalInstance.setApplicantName(SecurityUtils.getLoginUser().getNickName()); approvalInstance.setApplyTime(LocalDateTime.now()); approvalInstance.setDeleted((byte) 0); approvalInstance.setCreateUser(SecurityUtils.getUserId()); approvalInstance.setUpdateUser(SecurityUtils.getUserId()); approvalInstance.setDeptId(enterpriseNews.getDeptId()); approvalInstanceMapper.insert(approvalInstance); approveProcessConfigNodeUtils.createCurrentNodeAndTasks(approvalInstance); sendApproveNotice(approvalInstance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstance.getId())); } private void sendApproveNotice(ApprovalInstance instance, List<ApprovalTask> tasks) { if (instance == null || tasks == null || tasks.isEmpty()) { return; } List<Long> approverIds = tasks.stream() .map(ApprovalTask::getApproverId) .filter(id -> id != null && id > 0) .distinct() .collect(Collectors.toList()); if (approverIds.isEmpty()) { return; } String title = StringUtils.isNotEmpty(instance.getTemplateName()) ? instance.getTemplateName() : "å®¡æ¹æé"; String message = "审æ¹åå· " + instance.getInstanceNo() + " éè¦æ¨å®¡æ¹"; String jumpPath = "/approvalInstance?id=" + instance.getId(); sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath); } } src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,10 @@ package com.ruoyi.collaborativeApproval.vo; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews; import lombok.Data; @Data public class EnterpriseNewsVo extends EnterpriseNews { private String createUserName; } src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java
@@ -16,6 +16,7 @@ APPROVED(3, "å·²éè¿"), REJECTED(4, "已驳å"); private final Integer value; private final String label; src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,143 @@ package com.ruoyi.common.enums; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; /** * ä¼ä¸æ°é»ç¶ææä¸¾ç±» * * @author ruoyi * @date 2026-05-20 */ @Schema(description = "ä¼ä¸æ°é»ç¶ææä¸¾") public enum EnterpriseNewsStatusEnum implements BaseEnum<String> { /** * è稿 */ @Schema(description = "è稿") DRAFT("DRAFT", "è稿"), /** * å¾ å®¡æ¹ */ @Schema(description = "å¾ å®¡æ¹") PENDING("PENDING", "å¾ å®¡æ¹"), /** * å·²åå¸ */ @Schema(description = "å·²åå¸") PUBLISHED("PUBLISHED", "å·²åå¸"), /** * 驳å */ @Schema(description = "驳å") REJECTED("REJECTED", "驳å"), /** * å·²ä¸çº¿ */ @Schema(description = "å·²ä¸çº¿") OFFLINE("OFFLINE", "å·²ä¸çº¿"); /** * ç¶æç */ private final String code; /** * ç¶ææè¿° * -- GETTER -- * è·åç¶ææè¿° * * @return ç¶ææè¿° */ @Getter private final String description; EnterpriseNewsStatusEnum(String code, String description) { this.code = code; this.description = description; } /** * è·åç¶æç * * @return ç¶æç */ @JsonValue public String getCode() { return code; } @Override public String getValue() { return ""; } /** * æ ¹æ®ç¶æç è·åæä¸¾ * * @param code ç¶æç * @return æä¸¾å¼ */ @JsonCreator public static EnterpriseNewsStatusEnum getByCode(String code) { for (EnterpriseNewsStatusEnum status : values()) { if (status.code.equals(code)) { return status; } } throw new IllegalArgumentException("Invalid enterprise news status code: " + code); } /** * 夿æ¯å¦ä¸ºèç¨¿ç¶æ * * @return æ¯å¦ä¸ºèç¨¿ç¶æ */ public boolean isDraft() { return DRAFT.equals(this); } /** * 夿æ¯å¦ä¸ºå¾ 审æ¹ç¶æ * * @return æ¯å¦ä¸ºå¾ 审æ¹ç¶æ */ public boolean isPending() { return PENDING.equals(this); } /** * 夿æ¯å¦ä¸ºå·²åå¸ç¶æ * * @return æ¯å¦ä¸ºå·²åå¸ç¶æ */ public boolean isPublished() { return PUBLISHED.equals(this); } /** * 夿æ¯å¦ä¸ºé©³åç¶æ * * @return æ¯å¦ä¸ºé©³åç¶æ */ public boolean isRejected() { return REJECTED.equals(this); } /** * 夿æ¯å¦ä¸ºå·²ä¸çº¿ç¶æ * * @return æ¯å¦ä¸ºå·²ä¸çº¿ç¶æ */ public boolean isOffline() { return OFFLINE.equals(this); } } src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.project.system.domain.SysUserDept; import com.ruoyi.project.system.domain.vo.SysUserDeptVo; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -15,4 +16,28 @@ List<SysUserDeptVo> userLoginFacotryList(@Param("userDeptVo") SysUserDeptVo userDeptVo); List<Map<String, Object>> setSchemeApplicableStaffUserInfo(@Param("ids") List<Long> ids); @Select("<script>" + "select count(distinct sud.user_id) " + "from sys_user_dept sud " + "inner join sys_user su on su.user_id = sud.user_id " + "where su.del_flag = '0' " + "and sud.dept_id in " + "<foreach collection='deptIds' item='deptId' open='(' separator=',' close=')'>" + "#{deptId}" + "</foreach>" + "</script>") Long countDistinctUserIdsByDeptIds(@Param("deptIds") List<Long> deptIds); @Select("<script>" + "select distinct sud.user_id " + "from sys_user_dept sud " + "inner join sys_user su on su.user_id = sud.user_id " + "where su.del_flag = '0' " + "and sud.dept_id in " + "<foreach collection='deptIds' item='deptId' open='(' separator=',' close=')'>" + "#{deptId}" + "</foreach>" + "</script>") List<Long> selectDistinctUserIdsByDeptIds(@Param("deptIds") List<Long> deptIds); } src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java
@@ -1,12 +1,14 @@ package com.ruoyi.project.system.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysNotice; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper; import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysNotice; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.domain.SysUserDept; import com.ruoyi.project.system.mapper.SysDeptMapper; @@ -15,11 +17,15 @@ import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.project.system.service.ISysNoticeService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * å ¬å æå¡å±å®ç° @@ -28,13 +34,16 @@ */ @Service @RequiredArgsConstructor public class SysNoticeServiceImpl extends ServiceImpl<SysNoticeMapper, SysNotice> implements ISysNoticeService { private final SysNoticeMapper noticeMapper; private final SysUserMapper userMapper; private final SysDeptMapper deptMapper; private final SysUserDeptMapper userDeptMapper; private final UnipushService unipushService; public class SysNoticeServiceImpl extends ServiceImpl<SysNoticeMapper, SysNotice> implements ISysNoticeService { private static final Pattern ENTERPRISE_NEWS_ID_PATTERN = Pattern.compile("[?&]id=(\\d+)"); private final SysNoticeMapper noticeMapper; private final SysUserMapper userMapper; private final SysDeptMapper deptMapper; private final SysUserDeptMapper userDeptMapper; private final UnipushService unipushService; private final EnterpriseNewsMapper enterpriseNewsMapper; /** * æ¥è¯¢å ¬åä¿¡æ¯ @@ -77,11 +86,26 @@ * @param notice å ¬åä¿¡æ¯ * @return ç»æ */ @Override public int updateNotice(SysNotice notice) { return noticeMapper.updateNotice(notice); } @Override @Transactional(rollbackFor = Exception.class) public int updateNotice(SysNotice notice) { if (notice == null || notice.getNoticeId() == null) { return 0; } SysNotice dbNotice = noticeMapper.selectNoticeById(notice.getNoticeId()); if (dbNotice == null) { return 0; } boolean needSyncNewsReadCount = isEnterpriseNewsNotice(dbNotice) && notice.getStatus() != null && !notice.getStatus().equals(dbNotice.getStatus()); int rows = noticeMapper.updateNotice(notice); if (rows > 0 && needSyncNewsReadCount) { syncEnterpriseNewsReadCount(dbNotice.getJumpPath()); } return rows; } /** * å é¤å ¬å对象 @@ -115,13 +139,20 @@ } @Override public int readAll() { Long userId = SecurityUtils.getUserId(); return noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate() .eq(SysNotice::getConsigneeId, userId) .eq(SysNotice::getStatus, "0") .set(SysNotice::getStatus, "1")); } public int readAll() { Long userId = SecurityUtils.getUserId(); List<SysNotice> unreadNotices = noticeMapper.selectList(Wrappers.<SysNotice>lambdaQuery() .eq(SysNotice::getConsigneeId, userId) .eq(SysNotice::getStatus, "0")); int rows = noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate() .eq(SysNotice::getConsigneeId, userId) .eq(SysNotice::getStatus, "0") .set(SysNotice::getStatus, "1")); if (rows > 0) { syncEnterpriseNewsReadCount(unreadNotices); } return rows; } @Override public void simpleNoticeByUser(String title, String message, List<Long> consigneeId, String jumpPath) { @@ -211,18 +242,72 @@ @Override @Transactional(rollbackFor = Exception.class) public boolean appReadNotice(Long noticeId) { if (noticeId == null) { return false; public boolean appReadNotice(Long noticeId) { if (noticeId == null) { return false; } SysNotice sysNotice = noticeMapper.selectNoticeById(noticeId); if (sysNotice == null) { return false; } sysNotice.setStatus("1"); return noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate() .eq(SysNotice::getNoticeId, noticeId) .eq(SysNotice::getStatus, "0") .set(SysNotice::getStatus, "1")) > 0; } } } sysNotice.setStatus("1"); boolean updated = noticeMapper.update(null, Wrappers.<SysNotice>lambdaUpdate() .eq(SysNotice::getNoticeId, noticeId) .eq(SysNotice::getStatus, "0") .set(SysNotice::getStatus, "1")) > 0; if (updated) { syncEnterpriseNewsReadCount(sysNotice.getJumpPath()); } return updated; } private boolean isEnterpriseNewsNotice(SysNotice sysNotice) { return sysNotice != null && sysNotice.getJumpPath() != null && sysNotice.getJumpPath().startsWith("/enterpriseNews?id="); } private void syncEnterpriseNewsReadCount(List<SysNotice> notices) { if (notices == null || notices.isEmpty()) { return; } Set<String> jumpPaths = new HashSet<>(); for (SysNotice notice : notices) { if (isEnterpriseNewsNotice(notice)) { jumpPaths.add(notice.getJumpPath()); } } for (String jumpPath : jumpPaths) { syncEnterpriseNewsReadCount(jumpPath); } } private void syncEnterpriseNewsReadCount(String jumpPath) { Long newsId = parseEnterpriseNewsId(jumpPath); if (newsId == null) { return; } long readCount = noticeMapper.selectCount(Wrappers.<SysNotice>lambdaQuery() .eq(SysNotice::getStatus, "1") .eq(SysNotice::getJumpPath, jumpPath)); EnterpriseNews enterpriseNews = new EnterpriseNews(); enterpriseNews.setId(newsId); enterpriseNews.setReadCount((int) readCount); enterpriseNewsMapper.updateById(enterpriseNews); } private Long parseEnterpriseNewsId(String jumpPath) { if (jumpPath == null || !jumpPath.startsWith("/enterpriseNews")) { return null; } Matcher matcher = ENTERPRISE_NEWS_ID_PATTERN.matcher(jumpPath); if (!matcher.find()) { return null; } try { return Long.parseLong(matcher.group(1)); } catch (NumberFormatException e) { return null; } } } src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
@@ -59,6 +59,7 @@ StaffLeave staffLeave = new StaffLeave(); staffLeave.setStaffOnJobId(staffLeaveDto.getStaffOnJobId()); staffLeave.setReason(staffLeaveDto.getReason()); staffLeave.setLeaveDate(staffLeaveDto.getLeaveDate()); String reason = staffLeaveDto.getReason(); if (StaffLeaveReasonOther.getCode().equals(reason)){ staffLeave.setRemark(staffLeaveDto.getRemark()); src/main/resources/mapper/approve/ApprovalInstanceMapper.xml
@@ -24,16 +24,28 @@ <result column="deleted" property="deleted" /> </resultMap> <select id="listPage" resultType="com.ruoyi.approve.bean.vo.ApprovalInstanceVo"> select ai.*,su.nick_name as create_user_name from select ai.*,su.nick_name as create_user_name from approval_instance ai left join sys_user su on ai.create_user = su.user_id <where> deleted = 0 <if test="ew.instanceNo != null"> and instance_no like concat('%',#{ew.instanceNo},'%') and ai.instance_no like concat('%',#{ew.instanceNo},'%') </if> <if test="ew.templateName != null"> and template_name like concat('%',#{ew.templateName},'%') and ai.template_name like concat('%',#{ew.templateName},'%') </if> <if test="ew.templateId != null "> and ai. template_id = #{ew.templateId} </if> <if test="ew.businessType != null "> and ai. business_type = #{ew.businessType} </if> <if test="ew.createTime != null"> and ai.create_time between to_date(#{ew.createTimeStart}) and to_date(#{ew.createTimeEnd}) </if> <if test="ew.status != null"> and ai.status = #{ew.status} </if> </where> order by ai.id desc src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNews"> <id column="id" property="id" /> <result column="title" property="title" /> <result column="summary" property="summary" /> <result column="content" property="content" /> <result column="category" property="category" /> <result column="read_scope" property="readScope" /> <result column="is_required" property="isRequired" /> <result column="status" property="status" /> <result column="required_read_count" property="requiredReadCount" /> <result column="read_count" property="readCount" /> <result column="create_user" property="createUser" /> <result column="create_time" property="createTime" /> <result column="update_user" property="updateUser" /> <result column="update_time" property="updateTime" /> <result column="dept_id" property="deptId" /> </resultMap> <select id="listPage" resultType="com.ruoyi.collaborativeApproval.vo.EnterpriseNewsVo"> select en.*, u.nick_name as create_user_name from enterprise_news en left join sys_user u on en.create_user = u.user_id <where> <if test="enterpriseNewsDto.title != null and enterpriseNewsDto.title != ''"> and en.title like concat('%',#{enterpriseNewsDto.title},'%') </if> <if test="enterpriseNewsDto.category != null and enterpriseNewsDto.category != ''"> and en.category = #{enterpriseNewsDto.category} </if> <if test="enterpriseNewsDto.status != null "> and en.status = #{enterpriseNewsDto.status} </if> <if test="enterpriseNewsDto.createUser != null and enterpriseNewsDto.createUser != ''"> and en.create_user = #{enterpriseNewsDto.createUser} </if> <if test="enterpriseNewsDto.createTimeStart != null and enterpriseNewsDto.createTimeEnd != null"> and en.create_time between #{enterpriseNewsDto.createTimeStart} and #{enterpriseNewsDto.createTimeEnd} </if> </where> </select> </mapper> src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept"> <id column="id" property="id" /> <result column="news_id" property="newsId" /> <result column="dept_id" property="deptId" /> <result column="create_time" property="createTime" /> </resultMap> </mapper> src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser"> <id column="id" property="id" /> <result column="news_id" property="newsId" /> <result column="user_id" property="userId" /> <result column="create_time" property="createTime" /> </resultMap> </mapper> src/main/resources/mapper/staff/StaffLeaveMapper.xml
@@ -18,15 +18,20 @@ soj.emergency_contact as emergencyContact, soj.emergency_contact_phone as emergencyContactPhone, sp.post_name as postName, sd.dept_name as deptName sd.dept_name as deptName, se.education as first_study, se.major as profession FROM staff_leave LEFT JOIN staff_on_job soj ON soj.id = staff_leave.staff_on_job_id LEFT JOIN sys_post sp ON sp.post_id = soj.sys_post_id LEFT JOIN sys_dept sd ON sd.dept_id = soj.sys_dept_id where 1=1 LEFT JOIN staff_on_job soj ON soj.id = staff_leave.staff_on_job_id LEFT JOIN sys_post sp ON sp.post_id = soj.sys_post_id LEFT JOIN sys_dept sd ON sd.dept_id = soj.sys_dept_id LEFT JOIN staff_education se ON se.staff_on_job_id = staff_leave.staff_on_job_id AND se.id = ( SELECT MAX(se2.id) FROM staff_education se2 WHERE se2.staff_on_job_id = staff_leave.staff_on_job_id ) WHERE 1=1 <if test="c.staffName != null and c.staffName != '' "> AND soj.staff_name LIKE CONCAT('%',#{c.staffName},'%') </if> src/main/resources/mapper/system/SysNoticeMapper.xml
@@ -10,11 +10,16 @@ <result property="noticeType" column="notice_type" /> <result property="noticeContent" column="notice_content" /> <result property="status" column="status" /> <result property="senderId" column="sender_id" /> <result property="consigneeId" column="consignee_id" /> <result property="jumpPath" column="jump_path" /> <result property="appJumpPath" column="app_jump_path" /> <result property="createBy" column="create_by" /> <result property="createTime" column="create_time" /> <result property="updateBy" column="update_by" /> <result property="updateTime" column="update_time" /> <result property="remark" column="remark" /> <result property="tenantId" column="tenant_id" /> </resultMap> <sql id="selectNoticeVo">