# CompRoomNotifyServiceImpl.java

    package cloud.wconnect.frontoffice.service.comproom.impl;

    import cloud.wconnect.commonlib.component.BeanMapper;
    import cloud.wconnect.commonlib.cons.EmailConfigCons;
    import cloud.wconnect.commonlib.cons.FunctionCons;
    import cloud.wconnect.commonlib.cons.NotifySubjectI18nCons;
    import cloud.wconnect.commonlib.pojo.dto.ApproveLevelDTO;
    import cloud.wconnect.commonlib.pojo.dto.NotifyDTO;
    import cloud.wconnect.commonlib.pojo.dto.NotifyIdentityDTO;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.pojo.dto.internationalization.InternationalizationDateTimeDTO;
    import cloud.wconnect.commonlib.pojo.dto.line.MoreApprovalMsgParm;
    import cloud.wconnect.commonlib.pojo.dto.line.SingleApprovalMsgParm;
    import cloud.wconnect.commonlib.service.NotifyInternalService;
    import cloud.wconnect.commonlib.service.PropertyInternalService;
    import cloud.wconnect.commonlib.service.UserInternalService;
    import cloud.wconnect.commonlib.util.*;
    import cloud.wconnect.frontoffice.cons.ApproveStatusEnum;
    import cloud.wconnect.frontoffice.cons.FunctionPointEnum;
    import cloud.wconnect.frontoffice.cons.comproom.CompRoomColumnEnum;
    import cloud.wconnect.frontoffice.cons.comproom.CompRoomNotifyConfigTypeEnum;
    import cloud.wconnect.frontoffice.entity.adjustment.AdjEmailConfig;
    import cloud.wconnect.frontoffice.entity.comproom.*;
    import cloud.wconnect.frontoffice.pojo.vo.comproom.CompRoomApproveLevelVO;
    import cloud.wconnect.frontoffice.pojo.vo.comproom.CompRoomEmailVO;
    import cloud.wconnect.frontoffice.service.comproom.*;
    import com.alibaba.fastjson.JSONObject;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.common.collect.Lists;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    import org.thymeleaf.TemplateEngine;
    import org.thymeleaf.context.Context;

    import java.text.MessageFormat;
    import java.util.*;
    import java.util.stream.Collectors;

    /**
     * 通知业务层
     *
     * @author lichen
     * @date 2023/8/21
     */
    @Service
    @DS("logbook")
    @Slf4j
    public class CompRoomNotifyServiceImpl implements ICompRoomNotifyService {

        @Autowired
        private PropertyInternalService propertyInternalService;
        @Autowired
        private ICompRoomApproveConfigService approveConfigService;
        @Autowired
        private BeanMapper beanMapper;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private UserInternalService userInternalService;
        @Autowired
        private TemplateEngine templateEngine;
        @Autowired
        private NotifyInternalService notifyInternalService;
        @Autowired
        private LineMessageUtil lineMessageUtil;
        @Autowired
        private ICompRoomApproveLogService approveLogService;
        @Value("${here.link.comp-room}")
        private String hereLink;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;
        @Autowired
        private ICompRoomApproveLevelService approveLevelService;
        @Autowired
        private ICompRoomEmailConfigService emailConfigService;

        /**
         * 通知审批人
         * 使用场景：一条数据走审批流程过程中，通知审批人进行审批
         *
         * @param compRoom 免费房数据
         * @return void
         * @author lichen
         * @date 2023/11/24
         */
        @Override
        public void notifyApprover(RqCompRoomForm compRoom) {
            //获取资产信息
            Integer propertyId = compRoom.getPropertyId();
            PropertyDTO propertyDTO = propertyInternalService.getOne(propertyId);

            //获取用户自定义的主题前缀和主题后缀
            CompRoomEmailConfig emailConfig = emailConfigService.getByPropertyIdAndType(propertyDTO.getId(), CompRoomNotifyConfigTypeEnum.WAIT_FOR_APPROVING.getType());
            if (Objects.isNull(emailConfig)) {
                emailConfig = new CompRoomEmailConfig();
                emailConfig.setStatus(true);
            }
            if (!emailConfig.getStatus()) {
                log.warn("Comp Room notify approver end, email config is close.");
                return;
            }

            //获取默认主题
            String defaultSubject = getDefaultSubject(propertyDTO);

            //获取通知主题
            String subject = StringUtils.isNotBlank(emailConfig.getSubject()) ? emailConfig.getSubject() : defaultSubject;

            //获取免费房数据的通知对象
            List<NotifyIdentityDTO> identityList = getNotifyIdentity(compRoom);
            if (CollectionUtils.isEmpty(identityList)) {
                return;
            }
            //获取邮件通知内容
            String emailContent = getEmailContent(ApproveStatusEnum.APPROVEING.getStatus(), propertyDTO, Lists.newArrayList(compRoom), defaultSubject);
            //获取line通知内容
            JSONObject lineMsg = getSingleApprovalLineMsg(propertyDTO, compRoom, ApproveStatusEnum.APPROVEING.getStatus());
            //发送通知
            doSendNotify(propertyDTO, subject, identityList, FunctionPointEnum.COMP_ROOM_APPROVE.getFunctionPoint(),
                    emailContent, lineMsg);
        }

        /**
         * 通知下一个审批节点的审批人
         * 使用场景：审批层级发生变化时，推送至下一个审批节点的审批人
         *
         * @param compRoomList     免费房数据集合
         * @param nextApproveLevel 下一个审批节点
         * @return void
         * @author lichen
         * @date 2023/11/24
         */
        @Override
        public void notifyNextApprovalNodeApprover(List<RqCompRoomForm> compRoomList, CompRoomApproveLevel nextApproveLevel) {
            if (CollectionUtils.isEmpty(compRoomList)) {
                return;
            }
            //获取资产信息
            Integer propertyId = compRoomList.get(0).getPropertyId();
            PropertyDTO propertyDTO = propertyInternalService.getOne(propertyId);
            String language = propertyDTO.getLanguage();

            //获取用户自定义的主题前缀和主题后缀
            CompRoomEmailConfig emailConfig = emailConfigService.getByPropertyIdAndType(propertyDTO.getId(), CompRoomNotifyConfigTypeEnum.WAIT_FOR_APPROVING.getType());
            if (Objects.isNull(emailConfig)) {
                emailConfig = new CompRoomEmailConfig();
                emailConfig.setStatus(true);
            }
            if (!emailConfig.getStatus()) {
                log.warn("Comp Room notify approver end, email config is close.");
                return;
            }

            //获取默认主题
            String defaultSubject = getDefaultSubject(propertyDTO);

            //获取通知主题
            String subject = StringUtils.isNotBlank(emailConfig.getSubject()) ? emailConfig.getSubject() : defaultSubject;

            //查询下一个节点的审批人
            List<Integer> nextApprover = approveConfigService.listByLevelId(nextApproveLevel.getPropertyId(), nextApproveLevel.getId())
                    .stream().map(CompRoomApproveConfig::getUserId).toList();
            //审批人集合
            List<NotifyIdentityDTO> identitys = Lists.newArrayListWithCapacity(nextApprover.size());
            identitys.addAll(nextApprover.stream().map(userId -> new NotifyIdentityDTO(EmailConfigCons.SOURCE_USER, userId,
                    EmailConfigCons.TARGET_TYPE_TO, "")).toList());
            //抄送对象集合
            if (StringUtils.isNotBlank(nextApproveLevel.getCc()) && !nextApproveLevel.getCc().equals("[]")) {
                List<NotifyIdentityDTO> identitysByCC = JsonUtils.convertStringToList(objectMapper, nextApproveLevel.getCc(), NotifyIdentityDTO.class);
                identitysByCC.forEach(cc -> cc.setTargetType(EmailConfigCons.TARGET_TYPE_CC));
                identitys.addAll(identitysByCC);
            }

            //获取邮件通知内容
            String emailContent = getEmailContent(ApproveStatusEnum.APPROVEING.getStatus(), propertyDTO, compRoomList, defaultSubject);

            //line消息内容
            JSONObject lineMsg;
            if (compRoomList.size() == 1) {
                lineMsg = getSingleApprovalLineMsg(propertyDTO, compRoomList.get(0), ApproveStatusEnum.APPROVEING.getStatus());
            } else {
                String linkUrl = MessageFormat.format(hereLink + "?fromPage=email&property={0}&tenant={1}", propertyDTO.getAbbr(), propertyDTO.getTenantSymbol());

                LinkedHashMap<String, String> businessMap = new LinkedHashMap<>();
                List<String> guestNames = compRoomList.stream().map(RqCompRoomForm::getGuestName).toList();
                businessMap.put(i18nMessageUtils.message(CompRoomColumnEnum.GUEST_NAME.getI18nCode(), language),
                        StringUtils.join(guestNames, ";"));

                lineMsg = lineMessageUtil.generateMoreApprovalMsg(MoreApprovalMsgParm.builder()
                        .propertyName(propertyDTO.getName())
                        .propertyId(propertyDTO.getId())
                        .functionName(i18nMessageUtils.message(FunctionCons.COMP_ROOM, language))
                        .approveStatus(ApproveStatusEnum.APPROVEING.getStatus())
                        .count(compRoomList.size())
                        .link(linkUrl)
                        .businessMap(businessMap)
                        .build());
            }

            //发送通知
            doSendNotify(propertyDTO, subject, identitys, FunctionPointEnum.COMP_ROOM_APPROVE.getFunctionPoint(),
                    emailContent, lineMsg);
        }

        /**
         * 审批通过时，通知给责任人
         * 使用场景：审批层级发生变化导致审批通过时，通知给责任人
         *
         * @param compRoomList 免费房数据集合
         * @return void
         * @author lichen
         * @date 2023/11/24
         */
        @Override
        public void batchNotifyCreateUserByApproved(List<RqCompRoomForm> compRoomList) {
            if (CollectionUtils.isEmpty(compRoomList)) {
                return;
            }

            //获取资产信息
            Integer propertyId = compRoomList.get(0).getPropertyId();
            PropertyDTO propertyDTO = propertyInternalService.getOne(propertyId);

            String language = propertyDTO.getLanguage();
            //功能名称
            String functionName = i18nMessageUtils.message(FunctionCons.COMP_ROOM, propertyDTO.getLanguage());
            //设置默认主题
            String defaultSubject = i18nMessageUtils.message(NotifySubjectI18nCons.APPROVAL_PASSED, language, functionName, propertyDTO.getName());

            String linkUrl = MessageFormat.format(hereLink + "?fromPage=email&property={0}&tenant={1}", propertyDTO.getAbbr(), propertyDTO.getTenantSymbol());

            //按照创建人分组
            Map<Integer, List<RqCompRoomForm>> createUser2CompRoomList = compRoomList.stream().collect(Collectors.groupingBy(RqCompRoomForm::getCreatedBy));

            for (Map.Entry<Integer, List<RqCompRoomForm>> entry : createUser2CompRoomList.entrySet()) {
                Integer createUser = entry.getKey();
                if (createUser == 0) continue;

                List<RqCompRoomForm> compRoomListByCreateUser = entry.getValue();

                //获取邮件通知内容
                String emailContent = getEmailContent(ApproveStatusEnum.APPROVED.getStatus(), propertyDTO, compRoomListByCreateUser, defaultSubject);
                //获取line通知内容
                JSONObject lineMsg;
                if (compRoomListByCreateUser.size() == 1) {
                    lineMsg = getSingleApprovalLineMsg(propertyDTO, compRoomListByCreateUser.get(0), ApproveStatusEnum.APPROVED.getStatus());
                } else {
                    LinkedHashMap<String, String> businessMap = new LinkedHashMap<>();
                    List<String> guestNames = compRoomListByCreateUser.stream().map(RqCompRoomForm::getGuestName).toList();
                    businessMap.put(i18nMessageUtils.message(CompRoomColumnEnum.GUEST_NAME.getI18nCode(), language),
                            StringUtils.join(guestNames, ";"));

                    lineMsg = lineMessageUtil.generateMoreApprovalMsg(MoreApprovalMsgParm.builder()
                            .propertyName(propertyDTO.getName())
                            .propertyId(propertyDTO.getId())
                            .functionName(i18nMessageUtils.message(FunctionCons.COMP_ROOM, language))
                            .approveStatus(ApproveStatusEnum.APPROVED.getStatus())
                            .count(compRoomListByCreateUser.size())
                            .link(linkUrl)
                            .businessMap(businessMap)
                            .build());
                }

                //通知人
                ArrayList<NotifyIdentityDTO> identitys = Lists.newArrayList(new NotifyIdentityDTO(EmailConfigCons.SOURCE_USER,
                        createUser, EmailConfigCons.TARGET_TYPE_TO, ""));

                //发送通知
                doSendNotify(propertyDTO, defaultSubject, identitys,
                        FunctionPointEnum.COMP_ROOM_APPROVED_NOTIFY_CREATE_USER.getFunctionPoint(), emailContent, lineMsg);
            }
        }

        /**
         * 审批通过或审批拒绝时，通知给创建人
         * 使用场景：一条数据走审批完结时，通知给责任人
         *
         * @param compRoom      免费房数据
         * @param approveStatus 审批状态
         * @return void
         * @author lichen
         * @date 2023/11/24
         */
        @Override
        public void notifyCreateUser(RqCompRoomForm compRoom, Integer approveStatus) {
            //创建人为0时不通知
            if (compRoom.getCreatedBy() == 0) return;
            //查询资产信息
            Integer propertyId = compRoom.getPropertyId();
            PropertyDTO propertyDTO = propertyInternalService.getOne(propertyId);
            String language = propertyDTO.getLanguage();
            //功能名称
            String functionName = i18nMessageUtils.message(FunctionCons.COMP_ROOM, propertyDTO.getLanguage());

            //通知人
            ArrayList<NotifyIdentityDTO> identitys = Lists.newArrayList(new NotifyIdentityDTO(EmailConfigCons.SOURCE_USER,
                    compRoom.getCreatedBy(), EmailConfigCons.TARGET_TYPE_TO, ""));
            //抄送对象集合
            CompRoomApproveLevel approveLevel = approveLevelService.getByApproveIndex(compRoom.getPropertyId(), compRoom.getApproveIndex());
            if (Objects.nonNull(approveLevel) && StringUtils.isNotBlank(approveLevel.getCc()) && !approveLevel.getCc().equals("[]")) {
                List<NotifyIdentityDTO> identitysByCC = JsonUtils.convertStringToList(objectMapper, approveLevel.getCc(), NotifyIdentityDTO.class);
                identitysByCC.forEach(cc -> cc.setTargetType(EmailConfigCons.TARGET_TYPE_CC));
                identitys.addAll(identitysByCC);
            }

            //设置默认主题
            String defaultSubject = "";
            if (approveStatus == ApproveStatusEnum.APPROVED.getStatus()) {
                defaultSubject = i18nMessageUtils.message(NotifySubjectI18nCons.APPROVAL_PASSED, language, functionName, propertyDTO.getName());
            } else {
                defaultSubject = i18nMessageUtils.message(NotifySubjectI18nCons.APPROVAL_REJECTED, language, functionName, propertyDTO.getName());
            }

            //获取邮件通知内容
            String emailContent = getEmailContent(approveStatus, propertyDTO, Lists.newArrayList(compRoom), defaultSubject);
            //获取line通知内容
            JSONObject lineMsg = getSingleApprovalLineMsg(propertyDTO, compRoom, approveStatus);

            //发送通知
            doSendNotify(propertyDTO, defaultSubject, identitys,
                    FunctionPointEnum.COMP_ROOM_APPROVED_NOTIFY_CREATE_USER.getFunctionPoint(), emailContent, lineMsg);
        }

        /**
         * 获取单条数据的line消息内容
         *
         * @param propertyDTO   资产DTO
         * @param compRoom      免费房
         * @param approveStatus 审批状态
         * @return com.alibaba.fastjson.JSONObject
         * @author lichen
         * @date 2023/11/25
         */
        private JSONObject getSingleApprovalLineMsg(PropertyDTO propertyDTO, RqCompRoomForm compRoom, Integer approveStatus) {
            InternationalizationDateTimeDTO dateTime = propertyDTO.getInternationalization().getDateTime();
            String longDate = dateTime.getLongDate();
            String timezone = propertyDTO.getTimezone();
            String language = propertyDTO.getLanguage();

            //审批日志树
            List<CompRoomApproveLevelVO> levelVOList = approveLogService.listApproveLogTree(compRoom, propertyDTO);
            List<ApproveLevelDTO> approveLevelDTOS = beanMapper.mapList(levelVOList, ApproveLevelDTO.class);

            LinkedHashMap<String, String> businessMap = new LinkedHashMap<>();
            businessMap.put(i18nMessageUtils.message(CompRoomColumnEnum.GUEST_NAME.getI18nCode(), language),
                    compRoom.getGuestName());
            //拼装checkInDate ~ checkOutDate
            long checkInDate = compRoom.getCheckInDate();
            if (checkInDate > 0) {
                businessMap.put(i18nMessageUtils.message(CompRoomColumnEnum.CHECK_IN_DATE.getI18nCode(), language),
                        InternationalizationUtils.formatDateTime(checkInDate, longDate, StringUtils.EMPTY, timezone, language));
            }
            long checkOutDate = compRoom.getCheckOutDate();
            if (checkOutDate > 0) {
                businessMap.put(i18nMessageUtils.message(CompRoomColumnEnum.CHECK_OUT_DATE.getI18nCode(), language),
                        InternationalizationUtils.formatDateTime(checkOutDate, longDate, StringUtils.EMPTY, timezone, language));
            }

            String linkUrl = MessageFormat.format(hereLink + "?fromPage=email&property={0}&tenant={1}", propertyDTO.getAbbr(), propertyDTO.getTenantSymbol());
            //获取line通知内容
            return lineMessageUtil.generateSingleApprovalMsg(SingleApprovalMsgParm.builder()
                    .propertyName(propertyDTO.getName())
                    .propertyId(propertyDTO.getId())
                    .approveStatus(approveStatus)
                    .functionName(i18nMessageUtils.message(FunctionCons.COMP_ROOM, language))
                    .approveLevels(approveLevelDTOS)
                    .businessMap(businessMap)
                    .link(linkUrl)
                    .build());
        }

        /**
         * 发送通知
         *
         * @param propertyDTO   资产dto
         * @param subject       主题
         * @param identityList  通知对象集合
         * @param functionPoint 功能点
         * @param emailContent  邮件内容
         * @param lineMsg       line消息
         * @return void
         * @author lichen
         * @date 2023/11/25
         */
        private void doSendNotify(PropertyDTO propertyDTO, String subject, List<NotifyIdentityDTO> identityList,
                                  Integer functionPoint, String emailContent, JSONObject lineMsg) {
            NotifyDTO notifyDTO = new NotifyDTO();
            notifyDTO.setPropertyId(propertyDTO.getId());
            notifyDTO.setFunctionPoint(functionPoint);
            notifyDTO.setSubject(subject);
            notifyDTO.setIdentityList(identityList);
            notifyDTO.setEmailContent(emailContent);
            notifyDTO.setLineContent(Lists.newArrayList(lineMsg));
            notifyInternalService.sendNotify(notifyDTO);
        }

        /**
         * 获取邮件内容
         *
         * @param approveStatus  审批状态
         * @param propertyDTO    资产DTO
         * @param compRoomList   免费房集合
         * @param defaultSubejct 默认主题
         * @return java.lang.String
         * @author lichen
         * @date 2023/11/25
         */
        private String getEmailContent(Integer approveStatus, PropertyDTO propertyDTO, List<RqCompRoomForm> compRoomList, String defaultSubejct) {
            //查询创建人
            Set<Integer> createBys = compRoomList.stream().map(RqCompRoomForm::getCreatedBy).collect(Collectors.toSet());
            Map<Integer, String> userId2Name = userInternalService.getNameMapByIds(propertyDTO.getTenantId(), createBys);

            List<CompRoomEmailVO> compRoomEmailVOS = compRoomList.stream().map(item -> convert(item, propertyDTO, userId2Name)).toList();
            //跳转链接
            String linkUrl = "";
            if (compRoomEmailVOS.size() == 1) {
                String guestName = compRoomEmailVOS.get(0).getGuestName();
                String firstName = "";
                if (guestName.contains(",")) {
                    firstName = Arrays.stream(guestName.split(",")).toList().get(0);
                } else {
                    firstName = guestName;
                }
                linkUrl = MessageFormat.format(hereLink + "?fromPage=email&property={0}&tenant={1}&guestName={2}",
                        propertyDTO.getAbbr(), propertyDTO.getTenantSymbol(), firstName);
            } else {
                linkUrl = MessageFormat.format(hereLink + "?fromPage=email&property={0}&tenant={1}", propertyDTO.getAbbr(), propertyDTO.getTenantSymbol());
            }
            //获取邮件内容
            Context context = new Context();
            context.setVariable("approveStatus", approveStatus);
            context.setVariable("emailVOS", compRoomEmailVOS);
            context.setVariable("hereLink", linkUrl);
            context.setVariable("propertyName", propertyDTO.getName());
            context.setVariable("functionName", i18nMessageUtils.message(FunctionCons.COMP_ROOM, propertyDTO.getLanguage()));
            String mailBody = templateEngine.process("comproom/compRoom-approval_" + propertyDTO.getLanguage(), context);
            return EmailUtil.getFullEmailContent(defaultSubejct, mailBody, propertyDTO.getLanguage());
        }

        /**
         * 转化comp room数据
         *
         * @param compRoom    comp room数据
         * @param propertyDTO 资产dto
         * @param userId2Name 用户集合
         * @return cloud.wconnect.frontoffice.pojo.vo.comproom.CompRoomEmailVO
         * @author lichen
         * @date 2023/11/24
         */
        private CompRoomEmailVO convert(RqCompRoomForm compRoom, PropertyDTO propertyDTO, Map<Integer, String> userId2Name) {
            InternationalizationDateTimeDTO dateTime = propertyDTO.getInternationalization().getDateTime();
            String longDate = dateTime.getLongDate();
            String hourClock = dateTime.getHourClock();
            String timezone = propertyDTO.getTimezone();
            String language = propertyDTO.getLanguage();

            //封装邮件对象
            CompRoomEmailVO compRoomEmailVO = beanMapper.map(compRoom, CompRoomEmailVO.class);
            compRoomEmailVO.setCreatedByName(userId2Name.get(compRoom.getCreatedBy()));
            compRoomEmailVO.setCheckInDateStr(InternationalizationUtils.formatDateTime(compRoom.getCheckInDate(), longDate, StringUtils.EMPTY, timezone, language));
            compRoomEmailVO.setCheckOutDateStr(InternationalizationUtils.formatDateTime(compRoom.getCheckOutDate(), longDate, StringUtils.EMPTY, timezone, language));
            compRoomEmailVO.setCreatedTimeStr(InternationalizationUtils.formatDateTime(compRoom.getCreatedTime(), longDate, hourClock, timezone, language));
            compRoomEmailVO.setApproveStatusDesc(i18nMessageUtils.message(ApproveStatusEnum.getI18nCode(compRoom.getApproveStatus()), language));

            List<String> confirmationList = JsonUtils.convertStringToList(objectMapper, compRoom.getConfirmation(), String.class);
            if (CollectionUtils.isNotEmpty(confirmationList)) {
                compRoomEmailVO.setConfirmations(StringUtils.join(confirmationList, ","));
            }
            return compRoomEmailVO;
        }

        /**
         * 获取免费房数据的通知对象
         *
         * @param compRoom 免费房数据
         * @return java.util.List<cloud.wconnect.commonlib.pojo.dto.NotifyIdentityDTO>
         * @author lichen
         * @date 2024/3/11
         */
        private List<NotifyIdentityDTO> getNotifyIdentity(RqCompRoomForm compRoom) {
            //审批层级
            CompRoomApproveLevel approveLevel = approveLevelService.getByApproveIndex(compRoom.getPropertyId(), compRoom.getApproveIndex());
            //审批配置
            List<CompRoomApproveConfig> approveConfigList = approveConfigService.listByLevelId(compRoom.getPropertyId(), approveLevel.getId());

            //初始化未审批的人等于当前配置的审批人
            Set<Integer> unApprover = approveConfigList.stream().map(CompRoomApproveConfig::getUserId).collect(Collectors.toSet());

            //查询已审批人
            List<CompRoomApproveLog> approveLogList = approveLogService.listCurrentApproveIndexLog(compRoom);
            //已审批人不为空时
            if (CollectionUtils.isNotEmpty(approveLogList)) {
                Set<Integer> alreadyApprover = approveLogList.stream().map(CompRoomApproveLog::getApproveBy).collect(Collectors.toSet());
                //未审批人等于 应该审批的人 减去 已审批人
                unApprover.removeAll(alreadyApprover);
            }

            //审批人集合
            List<NotifyIdentityDTO> identitys = Lists.newArrayListWithCapacity(unApprover.size());
            identitys.addAll(unApprover.stream().map(userId -> new NotifyIdentityDTO(EmailConfigCons.SOURCE_USER, userId,
                    EmailConfigCons.TARGET_TYPE_TO, "")).toList());
            //抄送对象集合
            if (StringUtils.isNotBlank(approveLevel.getCc()) && !approveLevel.getCc().equals("[]")) {
                List<NotifyIdentityDTO> identitysByCC = JsonUtils.convertStringToList(objectMapper, approveLevel.getCc(), NotifyIdentityDTO.class);
                identitysByCC.forEach(cc -> cc.setTargetType(EmailConfigCons.TARGET_TYPE_CC));
                identitys.addAll(identitysByCC);
            }
            return identitys;
        }

        /**
         * 获取默认主题
         *
         * @param propertyDTO 资产DTO
         * @return java.lang.String
         * @author lichen
         * @date 2025/1/16
         */
        private String getDefaultSubject(PropertyDTO propertyDTO) {
            //功能名称
            String functionName = i18nMessageUtils.message(FunctionCons.COMP_ROOM, propertyDTO.getLanguage());
            //默认主题的国际化code
            String defaultSubjectI18nCode = CompRoomNotifyConfigTypeEnum.getDefaultSubjectI18nCode(CompRoomNotifyConfigTypeEnum.WAIT_FOR_APPROVING.getType());
            //默认的主题
            return i18nMessageUtils.message(defaultSubjectI18nCode, propertyDTO.getLanguage(), functionName, propertyDTO.getName());
        }
    }