liyong
6 天以前 ed0d872dddf37672ceb9bc499099f65d63ed1ce3
feat(approve): 添加企业新闻审批功能并完善审批实例管理

- 在ApprovalInstance实体中添加日期格式化注解和时间字段
- 继承BaseController以增强审批实例和节点控制器功能
- 添加企业新闻相关DTO、VO和POJO实体类及数据库映射
- 扩展审批实例服务以支持企业新闻审批流程处理
- 实现企业新闻通知发送机制和阅读统计功能
- 更新系统公告服务以同步企业新闻阅读计数
- 完善员工请假服务中的日期设置逻辑
- 优化数据库查询语句以支持更精确的筛选条件
已添加21个文件
已修改12个文件
1465 ■■■■■ 文件已修改
src/main/java/com/ruoyi/approve/bean/dto/ApprovalInstanceDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/ApprovalInstanceController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/ApprovalInstanceNodeController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/ApprovalInstance.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeDeptController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/EnterpriseNewsScopeUserController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/EnterpriseNewsDto.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsMapper.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeDeptMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/EnterpriseNewsScopeUserMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNews.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeDept.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/EnterpriseNewsScopeUser.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeDeptService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsScopeUserService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/EnterpriseNewsService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeDeptServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsScopeUserServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/EnterpriseNewsServiceImpl.java 378 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/vo/EnterpriseNewsVo.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/ApprovalStatusEnum.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/EnterpriseNewsStatusEnum.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java 169 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/ApprovalInstanceMapper.xml 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/EnterpriseNewsMapper.xml 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeDeptMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/EnterpriseNewsScopeUserMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/staff/StaffLeaveMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysNoticeMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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">