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.basic.enums.ApplicationTypeEnum;
|
import com.ruoyi.basic.enums.RecordTypeEnum;
|
import com.ruoyi.basic.utils.FileUtil;
|
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;
|
private final FileUtil fileUtil;
|
|
@Override
|
public IPage<EnterpriseNewsVo> listPage(Page<EnterpriseNewsVo> page, EnterpriseNewsDto enterpriseNewsDto) {
|
IPage<EnterpriseNewsVo> enterpriseNewsVoIPage = enterpriseNewsMapper.listPage(page, enterpriseNewsDto);
|
enterpriseNewsVoIPage.getRecords().forEach(enterpriseNewsVo -> {
|
enterpriseNewsVo.setStorageBlobDTOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNewsVo.getId()));
|
});
|
return enterpriseNewsVoIPage;
|
}
|
|
@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);
|
}
|
//添加附件
|
fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNews.getId(), enterpriseNewsDto.getStorageBlobDTOs());
|
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);
|
fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNews.getId(), enterpriseNewsDto.getStorageBlobDTOs());
|
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);
|
}
|
}
|