sinake
2 天以前 194ecd2dbc3a9c7eccfe5d9809ff947715960465
ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundServiceImpl.java
@@ -6,25 +6,32 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.ApplyTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.HttpClientKit;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.DtoConversionUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.project.common.FundNotifyMessageBuilder;
import com.ruoyi.project.common.IdGeneratorUtils;
import com.ruoyi.project.domain.*;
import com.ruoyi.project.domain.vo.*;
import com.ruoyi.project.mapper.*;
import com.ruoyi.project.service.*;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.ss.usermodel.*;
@@ -34,17 +41,16 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
/**
@@ -58,6 +64,10 @@
public class ServiceFundServiceImpl extends ServiceImpl<ServiceFundMapper, ServiceFund> implements IServiceFundService {
    @Autowired
    ServiceFundMapper serviceFundMapper;
    /** 专家劳务费 9 条费用控制规则校验(同一案例累计) */
    @Autowired
    private ExpertFeeValidateService expertFeeValidateService;
    @Autowired
    private DingTalkService dingTalkService;
@@ -134,6 +144,35 @@
    @Value("${spring.profiles.active}")
    private String active;
    @Autowired
    private ISysConfigService sysConfigService;
    /**
     * 审批单是否上传医院协友(致远)系统:0=不上传(测试环境),1=上传(正式环境)。
     *
     * <p>2026-10-09 新增:原来用 {@code spring.profiles.active == druid} 判断是否推送,
     * 测试环境与正式环境无法通过参数区分。改为系统参数控制。
     */
    private static final String CFG_UPLOAD_OA = "sys.approval.upload.oa";
    /** 参数缺省值:上传(保持正式环境原有行为) */
    private static final boolean DEFAULT_UPLOAD_OA = true;
    /** 审批单是否需要上传医院协友(致远)系统 */
    private boolean isUploadOaEnabled() {
        String value = null;
        try {
            value = sysConfigService.selectConfigByKey(CFG_UPLOAD_OA);
        } catch (Exception e) {
            log.warn("读取参数 {} 失败,按默认值 {} 处理", CFG_UPLOAD_OA, DEFAULT_UPLOAD_OA, e);
        }
        if (value == null || value.trim().isEmpty()) {
            return DEFAULT_UPLOAD_OA;
        }
        String v = value.trim();
        return "1".equals(v) || "true".equalsIgnoreCase(v) || "y".equalsIgnoreCase(v) || "on".equalsIgnoreCase(v);
    }
    /**
     * 致远系统流程退回
     *
@@ -176,7 +215,7 @@
            serviceFundSharedMapper.delfundsharedInfoById(null, serviceFund1.getId());
            //这个消息发送,就不在这做了,在审批记录的接口里做(即日志接口)
            //sendMeg(serviceFund1.getApplytype(), sysUser.getPhonenumber());
//            sendMeg(serviceFund1.getApplytype(), sysUser.getPhonenumber());
        }
        return true;
@@ -196,9 +235,15 @@
        String phone = null;
        String applytype = null;
        Long flowlevel = null;
        //钉钉通知用的单据信息
        Double amount = null;
        String donorName = null;
        String billNo = null;
        String travelers = null;
        String reason = null;
        if (serviceProcessVO.getApplytype().equals("0")) {
            ServiceReimbursement serviceReimbursement = new ServiceReimbursement();
            serviceReimbursement.setId(serviceProcessVO.getBackCode());
            serviceReimbursement.setId(StringUtils.isNotEmpty(serviceProcessVO.getBackCode()) ? Long.valueOf(serviceProcessVO.getBackCode()) : null);
            List<ServiceReimbursement> serviceReimbursementList = iServiceReimbursementService.queryList(serviceReimbursement);
            if (CollectionUtils.isEmpty(serviceReimbursementList)) {
                log.error("serviceReimbursementList没有查到数据:{}", serviceProcessVO.getBackCode());
@@ -210,9 +255,14 @@
            phone = serviceReimbursementList.get(0).getPhone();
            flowlevel = serviceReimbursementList.get(0).getFlowlevel();
            applytype = "0";
            amount = serviceReimbursementList.get(0).getAmountrequested();
            billNo = FundNotifyMessageBuilder.billNo(serviceReimbursementList.get(0).getBh(),
                    serviceReimbursementList.get(0).getId());
            travelers = serviceReimbursementList.get(0).getTravelers();
            reason = serviceReimbursementList.get(0).getReason();
        } else {
            ServiceFund serviceFund = new ServiceFund();
            serviceFund.setId(serviceProcessVO.getBackCode());
            serviceFund.setId(StringUtils.isNotEmpty(serviceProcessVO.getBackCode()) ? Long.valueOf(serviceProcessVO.getBackCode()) : null);
            List<ServiceFund> serviceFunds = queryInfoById(serviceFund);
            if (CollectionUtils.isEmpty(serviceFunds)) {
                log.error("serviceFunds没有查到数据:{}", serviceProcessVO.getBackCode());
@@ -223,28 +273,42 @@
            phone = serviceFunds.get(0).getPhone();
            flowlevel = serviceFunds.get(0).getFlowlevel();
            applytype = serviceFunds.get(0).getApplytype();
            amount = serviceFunds.get(0).getPretaxcost();
            donorName = serviceFunds.get(0).getDonorname();
            billNo = FundNotifyMessageBuilder.billNo(serviceFunds.get(0).getBh(),
                    serviceFunds.get(0).getId());
        }
        //将操作保存到fundflow表中
        ServiceFundflow serviceFundflow = new ServiceFundflow();
        serviceFundflow.setCreateBy("admin");
        serviceFundflow.setCreateTime(new Date());
        serviceFundflow.setUpdateBy("admin");
        serviceFundflow.setUpdateTime(new Date());
        serviceFundflow.setCheckusername(serviceProcessVO.getCheckusername());
        serviceFundflow.setFlowcontent(serviceProcessVO.getFlowcontent());
        serviceFundflow.setFlowconclusion(1);
        serviceFundflow.setFundtype(2);
        serviceFundflow.setFlowlevel(flowlevel.intValue());
        if (serviceProcessVO.getFlowconclusion() == 3) serviceFundflow.setFlowlevel(999);
        serviceFundflow.setApplytype(applytype);
        serviceFundflow.setFundid(serviceProcessVO.getBackCode());
        serviceFundflow.setCheckTime(serviceProcessVO.getCheckTime());
        fundflowService.save(serviceFundflow);
//        //将操作保存到fundflow表中
//        ServiceFundflow serviceFundflow = new ServiceFundflow();
//        serviceFundflow.setCreateBy("admin");
//        serviceFundflow.setCreateTime(new Date());
//        serviceFundflow.setUpdateBy("admin");
//        serviceFundflow.setUpdateTime(new Date());
//        serviceFundflow.setCheckusername(serviceProcessVO.getCheckusername());
//        serviceFundflow.setFlowcontent(serviceProcessVO.getFlowcontent());
//        serviceFundflow.setFlowconclusion(1);
//        serviceFundflow.setFundtype(2);
//        serviceFundflow.setFlowlevel(flowlevel.intValue());
//        if (StringUtils.isNotEmpty(serviceProcessVO.getFlowconclusion()) && serviceProcessVO.getFlowconclusion().equals("3"))
//            serviceFundflow.setFlowlevel(999);
//        serviceFundflow.setApplytype(applytype);
//        serviceFundflow.setFundid(StringUtils.isNotEmpty(serviceProcessVO.getBackCode()) ? Long.valueOf(serviceProcessVO.getBackCode()) : null);
//        serviceFundflow.setCheckTime(serviceProcessVO.getCheckTime());
//        fundflowService.save(serviceFundflow);
        SysUser sysUser = sysUserService.selectUserByUserName(userNo);
        sendMeg(serviceProcessVO, phone);
        //钉钉通知内容:单据信息(类型/报销人/金额/案例/编号)+ 审批人/审批时间/意见
        List<ConcurrentHashMap<String, Object>> notifyRows = FundNotifyMessageBuilder.newRows();
        FundNotifyMessageBuilder.addBillInfo(notifyRows, applytype, userName, amount, donorName, billNo);
        FundNotifyMessageBuilder.addTravelInfo(notifyRows, travelers, reason);
        FundNotifyMessageBuilder.addAuditResult(notifyRows, serviceProcessVO.getCheckusername(),
                serviceProcessVO.getCheckTime(),
                FundNotifyMessageBuilder.opinion(serviceProcessVO.getFlowconclusion(),
                        serviceProcessVO.getFlowcontent()));
        sendMeg(serviceProcessVO, phone, notifyRows);
        //发送信息保存
        ServiceSystemmessage serviceSystemmessage = new ServiceSystemmessage();
        serviceSystemmessage.setFundtype(1);
@@ -256,10 +320,46 @@
        serviceSystemmessage.setUpdateBy(sysUser.getNickName());
        serviceSystemmessage.setIsread(0);
        serviceSystemmessage.setMessagetype(1);
        serviceSystemmessage.setMessagetitle("财务系统信息");
        serviceSystemmessage.setMessagetitle("OPO系统审批");
        serviceSystemmessage.setMessagecontent(serviceProcessVO.getFlowcontent());
        iServiceSystemmessageService.save(serviceSystemmessage);
        return true;
    }
    @Override
    public Boolean updatecodepay(ServiceCodeAndPyaWay serviceCodeAndPyaWay) {
        Integer i = null;
        if (StringUtils.isNotEmpty(serviceCodeAndPyaWay.getApplytype()) && !serviceCodeAndPyaWay.getApplytype().equals("0")) {
            ServiceFund serviceFund = new ServiceFund();
            serviceFund.setId(serviceCodeAndPyaWay.getBackCode());
            serviceFund.setBh(serviceCodeAndPyaWay.getBh());
            serviceFund.setZffs(serviceCodeAndPyaWay.getZffs());
            serviceFund.setRiqi(serviceCodeAndPyaWay.getRiqi());
            i = serviceFundMapper.updateById(serviceFund);
            ServiceFundShared serviceFundShared = new ServiceFundShared();
            serviceFundShared.setSerfunid(serviceFund.getId());
            serviceFundShared.setZffs(serviceFund.getZffs());
            serviceFundShared.setRiqi(serviceFund.getRiqi());
            serviceFundShared.setBh(serviceFund.getBh());
            serviceFundSharedMapper.updateShareByfundid(serviceFundShared);
        } else {
            ServiceReimbursement serviceReimbursement = new ServiceReimbursement();
            serviceReimbursement.setId(serviceCodeAndPyaWay.getBackCode());
            serviceReimbursement.setBh(serviceCodeAndPyaWay.getBh());
            serviceReimbursement.setZffs(serviceCodeAndPyaWay.getZffs());
            serviceReimbursement.setRiqi(serviceCodeAndPyaWay.getRiqi());
            i = serviceReimbursementMapper.updateById(serviceReimbursement);
            ServiceReimbursementShared serviceReimbursementShared = new ServiceReimbursementShared();
            serviceReimbursementShared.setReimid(serviceReimbursement.getId());
            serviceReimbursementShared.setBh(serviceReimbursement.getBh());
            serviceReimbursementShared.setZffs(serviceReimbursement.getZffs());
            serviceReimbursementShared.setRiqi(serviceReimbursement.getRiqi());
            serviceReimbursementSharedMapper.updateReimShareByfundid(serviceReimbursementShared);
        }
        if (i == 0) return false;
        return true;
    }
@@ -334,6 +434,7 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> checkFund(CheckFundVO checkFundVO, LoginUser loginUser) {
        ServiceFund serviceFund = getById(checkFundVO.getFundid());
        Map<String, String> map = new HashMap<>();
@@ -341,6 +442,19 @@
        if (serviceFund == null) {
            map.put(HttpStatus.NO_CONTENT + "", "费用编号不正确");
            return map;
        }
        // 专家劳务费:审核“通过”前校验 9 条费用控制规则(同一案例累计);不通过则不阻断
        if (checkFundVO.getFlowconclusion() != null && checkFundVO.getFlowconclusion() == 1) {
            ExpertFeeCheckResult expertFeeResult = expertFeeValidateService.validateBeforeCheck(checkFundVO.getFundid());
            if (expertFeeResult.hasError()) {
                map.put(HttpStatus.ERROR + "", expertFeeResult.errorMessage());
                return map;
            }
            if (expertFeeResult.hasWarning()) {
                // 规则 5、6 仅提示,不阻断审核
                log.warn("专家劳务费审核校验提示:fundId={},{}", checkFundVO.getFundid(), expertFeeResult.warningMessage());
            }
        }
        Integer TotalLevel = 0;
@@ -369,6 +483,11 @@
        Integer RecordStatus = serviceFund.getRecordstatus();
        Integer FlowLevel = serviceFund.getFlowlevel().intValue();
        Integer OriginalFlowLevel = FlowLevel;
        //审批结论必填:原实现直接 == 1 拆箱,接口被直调传 null 会 NPE 500
        if (checkFundVO.getFlowconclusion() == null) {
            map.put(HttpStatus.ERROR + "", "审批结论不能为空");
            return map;
        }
        if (checkFundVO.getFlowconclusion() == 1) {
            CheckFlag = 1;
            if (TotalLevel == 0) {
@@ -384,7 +503,8 @@
            SysUser user = loginUser.getUser();
            if (serviceFund.getFlowlevel() == Long.valueOf(serviceFundflowrules.get(0).getFlowlevel() - 1) && serviceFund.getBackflowlevel() == 100) {
                log.info("财务退回再提交,出纳再次审批,之后提交到财务");
                serviceFund.setFinancechecher("审批人:" + user.getUserName() + " & 审批时间" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + " & 审批结果:通过");
//                serviceFund.setFinancechecher("审批人:" + user.getNickName() + " & 审批时间" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + " & 审批结果:通过");
                serviceFund.setFinancechecher(user.getNickName());
                serviceFund.setFlowlevel(serviceFundflowrules.get(0).getTotallevel().longValue());
                serviceFund.setRecordstatus(99);
@@ -396,8 +516,9 @@
                if (newSwitch == 1) {
                    aBoolean1 = sendData(serviceFund);
                    if (!aBoolean1) {
                        map.put("500", "发送失败");
                        return map;
                        // 推送医院协友系统失败:整个审批不生效(事务回滚),允许下次重新审批
                        log.error("费用审批单上传医院协友系统失败,审批不生效,fundId={},请重新审批", serviceFund.getId());
                        throw new ServiceException("医院协友系统接收失败,本次审批未生效,请稍后重新审批");
                    }
                }
                //保存审批流程表
@@ -406,6 +527,7 @@
                serviceFundflow.setCheckuserno(user.getUserName());
                serviceFundflow.setCheckusername(user.getNickName());
                serviceFundflow.setFundtype(2);
                serviceFundflow.setCheckTime(new Date());
                serviceFundflow.setApplytype(serviceFund.getApplytype());
                serviceFundflow.setFlowconclusion(CheckFlag);
                serviceFundflow.setFlowcontent("通过");
@@ -417,19 +539,19 @@
            List<Integer> roleIds = sysUserRoleMapper.getUserRoleByUserId(user.getUserId());
            if (roleIds != null && roleIds.contains(11)) {
                //11为财务
                serviceFund.setFinancechecher("审批人:" + user.getUserName() + " & 审批时间" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " & 审批结果:通过");
//                serviceFund.setFinancechecher("审批人:" + user.getNickName() + " & 审批时间" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " & 审批结果:通过");
                serviceFund.setFinancechecher(user.getNickName());
            }
            //记录一下,下一级的审批,以便于下一级退回后,发起者提交时,能再提到当前审批层级
            serviceFund.setBackflowlevel(FlowLevel);
        } else {
        } //else {
            CheckFlag = 2;
            if (CheckFlag == 2) {
                //应医院要求如果出现退回,直接退到发起者
                FlowLevel = 0;
                RecordStatus = -1;
                log.info("serviceFund进来了吗?????? :{},{}", RecordStatus, FlowLevel);
                System.out.println("serviceFund进来了吗??????");
            } else {
                RecordStatus = (FlowLevel + 1) * 2 - 1;
                FlowLevel = (FlowLevel - 1);
@@ -439,19 +561,24 @@
            }
            SysUser sysUser = sysUserService.selectUserByUserName(serviceFund.getUserno());
            ArrayList<ConcurrentHashMap<String, Object>> contentList = new ArrayList<>();
            ConcurrentHashMap cmap = new ConcurrentHashMap();
            cmap.put("审批人:", loginUser.getUser().getUserName());
            cmap.put("审批时间:", new Date());
            cmap.put("意见:", "不通过");
            if (StringUtils.isNotBlank(checkFundVO.getFlowcontent())) cmap.put("意见:", checkFundVO.getFlowcontent());
            contentList.add(cmap);
            DingTalkReqVo dingTalkReqVo = new DingTalkReqVo();
            dingTalkReqVo.setTitle("财务系统驳回信息");
            dingTalkReqVo.setNumber(sysUser.getPhonenumber());
            dingTalkReqVo.setContents(contentList);
            dingTalkService.sendNotification(dingTalkReqVo);
        }
            //审批未通过:单据信息 + 审批人/审批时间/意见(意见 = "审批未通过。" + 驳回意见)
            List<ConcurrentHashMap<String, Object>> contentList = FundNotifyMessageBuilder.newRows();
            FundNotifyMessageBuilder.addBillInfo(contentList, serviceFund.getApplytype(),
                    serviceFund.getUsername(), serviceFund.getPretaxcost(), serviceFund.getDonorname(),
                    FundNotifyMessageBuilder.billNo(serviceFund.getBh(), serviceFund.getId()));
            FundNotifyMessageBuilder.addAuditResult(contentList, loginUser.getUser().getNickName(), new Date(),
                    FundNotifyMessageBuilder.opinion(FundNotifyMessageBuilder.CONCLUSION_REJECT,
                            checkFundVO.getFlowcontent()));
            try {
                DingTalkReqVo dingTalkReqVo = new DingTalkReqVo();
                dingTalkReqVo.setTitle(FundNotifyMessageBuilder.TITLE);
                dingTalkReqVo.setNumber(sysUser.getPhonenumber());
                dingTalkReqVo.setContents(contentList);
                dingTalkService.sendNotification(dingTalkReqVo);
            } catch (Exception e) {
                log.error("费用---审批未通过钉钉通知失败,fundId={}", serviceFund.getId(), e);
            }
        //}
        serviceFund.setRecordstatus(RecordStatus);
        serviceFund.setFlowlevel(FlowLevel.longValue());
@@ -465,6 +592,7 @@
        serviceFundflow.setFundtype(2);
        serviceFundflow.setApplytype(serviceFund.getApplytype());
        serviceFundflow.setFlowconclusion(CheckFlag);
        serviceFundflow.setCheckTime(new Date());
        if (StringUtils.isNotBlank(checkFundVO.getFlowcontent())) {
            serviceFundflow.setFlowcontent(checkFundVO.getFlowcontent());
        } else {
@@ -475,24 +603,37 @@
        Boolean aBoolean = serviceFundflowService.saveData(serviceFundflow);
        log.info("sserviceFund保存的的值是-------- :{}", aBoolean);
        //053审批通过之后,就需要把“办公室主任”的名字填上
        if (checkFundVO.getFlowconclusion() == 1 && user.getUserName().equals("053")) {
            serviceFund.setOfficedirector(user.getNickName());
        //办公室审批通过之后,就需要把“办公室主任”的名字填上
        SysUser sysUsers = null;
        if (StringUtils.isNotEmpty(user.getUserName())) {
            sysUsers = sysUserMapper.selectUserByUserName(user.getUserName());
            log.info("费用sysUsers返回的值为:{}", sysUsers);
        }
        // 2026-10-09:推送条件由"当前审核人有 officedirector 角色"改为"本次审批后到达最后一级"。
        // 原写法在"最后一级审核人没有该角色"时永远不会推送,而"非最后一级的 officedirector"会提前推送。
        boolean uploadAtLastLevel = checkFundVO.getFlowconclusion() == 1
                && TotalLevel != null && TotalLevel != 0 && TotalLevel == OriginalFlowLevel + 1;
        if (uploadAtLastLevel) {
            // 仍只在该角色审批时记录办公室主任,保持字段语义不变
            if (sysUsers != null && sysUsers.getRoles() != null
                    && sysUsers.getRoles().stream().anyMatch(role -> "officedirector".equals(role.getRoleKey()))) {
                serviceFund.setOfficedirector(user.getNickName());
            }
            serviceFund.setUploadStates(1);
            //数据发送
            Boolean aBoolean1 = null;
            if (newSwitch == 1) {
                log.info("费用newSwitch返回的值为:{}", newSwitch);
                //搞一个开关,别影响老流程
                aBoolean1 = sendData(serviceFund);
                if (!aBoolean1) {
                    map.put("500", "发送失败");
                    return map;
                    // 推送医院协友系统失败:整个审批不生效(事务回滚),允许下次重新审批
                    log.error("费用审批单上传医院协友系统失败,审批不生效,fundId={},请重新审批", serviceFund.getId());
                    throw new ServiceException("医院协友系统接收失败,本次审批未生效,请稍后重新审批");
                }
            }
        }
        System.out.println("serviceFund的值是--------:" + serviceFund);
        log.info("开始更新的的值是--------");
        Boolean aBoolean1 = updateById(serviceFund);
        log.info("integer更新的的值是-------- :{}", aBoolean1);
        ServiceSystemmessage serviceSystemmessage = new ServiceSystemmessage();
@@ -552,9 +693,36 @@
    }
    /**
     * 审批单上传医院协友(致远)系统。
     *
     * <p>2026-10-09:外层包一层兜底,保证**任何异常都不会向外抛**(原来 strRes 为 null 时
     * 会在 parseObject 后取 code 触发 NPE,把整个审批请求打成 500)。
     * 返回 false 表示推送失败,调用方按"审批不生效、允许下次重新审批"处理。
     */
    public Boolean sendData(ServiceFund serviceFund) {
        // fund和funddetail的数据获取
        addFundSharedInfo(serviceFund.getId());
        if (!isUploadOaEnabled()) {
            // 上传开关关闭(如测试环境):跳过上传并视为成功,绝不能因此阻断审批
            log.info("审批单上传医院协友系统已关闭(sys.approval.upload.oa != 1),跳过上传并视为成功,fundId={}",
                    serviceFund == null ? null : serviceFund.getId());
            return true;
        }
        try {
            return doSendData(serviceFund);
        } catch (Throwable t) {
            log.error("费用审批单上传医院协友系统异常,审批不生效,fundId={}",
                    serviceFund == null ? null : serviceFund.getId(), t);
            return false;
        }
    }
    private Boolean doSendData(ServiceFund serviceFund) {
        // 2026-10-09:接住 addFundSharedInfo 的失败信号(附件上传失败时它会回滚分享表并返回 false)
        Boolean sharedOk = addFundSharedInfo(serviceFund.getId());
        if (sharedOk == null || !sharedOk) {
            log.error("费用报销单上传失败:分享表/附件环节失败,审批不生效,fundId={}", serviceFund.getId());
            return false;
        }
        List<ServiceFundShared> fundShareInfos = serviceFundSharedMapper.getFundShareInfoById(serviceFund.getId());
        if (CollectionUtils.isEmpty(fundShareInfos)) return false;
@@ -571,7 +739,7 @@
        // 主表字段数据
        Map<String, Object> data2 = new HashMap<>();
        data2.put("formmain_0831", getformmain_0831(fundShareInfos.get(0)));
        data2.put("formmain_0831", getformmain_0831(serviceFund));
        // 明细表字段数据,与附件的处理
        Map<String, List<Map<String, Object>>> map1 = formson_0832(serviceFunddetailShareds);
        data2.put("formson_0832", map1.get("formson_0832"));
@@ -579,32 +747,82 @@
        data.put("data", data2);
        //模板编号,由致远方提供,该参数决定发起协同系统中哪个流程
        data.put("templateCode", "001");
        data.put("templateCode", "fybxd_rzhc_ceshi");
        //是否为待发:0:新建-发送;1:新建-保存待发
        data.put("draft", "0");
        //协同标题区附件,Long型List,值为附件的Id。Id是附件接口响应结果中fileUrl字段的值
        data.put("attachments", null);
//        data.put("attachments", null);
        //协同公文的id
        data.put("relateDoc", "col|123,456;doc|321,654");
//        data.put("relateDoc", "col|123,456;doc|321,654");
        //未设置取模板设置的标题
        data.put("subject", "null");
        ServiceFund serviceFund1 = serviceFundMapper.selectById(serviceFund.getId());
        data.put("summaryId", serviceFund1.getSummaryId());
        map.put("data", data);
        String strRes = null;
        if (!active.equals("druid")) {
        if (isUploadOaEnabled()) {
            //如果是本地环境,就不调这个了
            String token = getToken();
            JSONObject json1 = JSONObject.parseObject(token);
            token = json1.get("id").toString();
            ObjectMapper objectMapper = new ObjectMapper();
            String json = null;
            if (serviceFund.getBackflowlevel() == 100L) {
                //再次发起
                strRes = HttpClientKit.postOpr(rexyurl, map.toString());
                try {
                    json = objectMapper.writeValueAsString(map);
                    log.error("-----------------再次发起的url为:{},  入参为:{}", rexyurl + "?token=" + token, json);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                strRes = HttpClientKit.postOpr(rexyurl + "?token=" + token, json);
            } else {
                //首次发起
                strRes = HttpClientKit.postOpr(xyurl, map.toString());
                try {
                    json = objectMapper.writeValueAsString(map);
                    log.error("-----------------首次发起的url为:{},  入参为:{}", xyurl + "?token=" + token, json);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                strRes = HttpClientKit.postOpr(xyurl + "?token=" + token, json);
                // 将summaryId保存起来,并将该值保存到fund中,用于再次发起时,使用(协友要求,再次发起时,带上这个值)
                JsonObject root = JsonParser.parseString(strRes).getAsJsonObject();
                String code = root.get("code").getAsString();
                if ("0".equals(code)) {
                    String appBusinessData = root.getAsJsonObject("data").get("app_bussiness_data").getAsString();
                    JsonObject appDataObj = JsonParser.parseString(appBusinessData).getAsJsonObject();
                    String summaryId = appDataObj.get("summaryId").getAsString();
                    serviceFund.setSummaryId(summaryId);
                    serviceFundMapper.updateById(serviceFund);
                }
            }
        }
        com.alibaba.fastjson2.JSONObject jsonObject = com.alibaba.fastjson2.JSONObject.parseObject(strRes);
        String code = jsonObject.getJSONObject("code").toString();
        if (!code.equals("0")) {
        log.error("------------------strRes的值为:{}", strRes);
        if (strRes == null || strRes.trim().isEmpty()) {
            // 医院协友系统无返回(超时/异常/未配置):推送失败,由调用方回滚整个审批
            log.error("费用审批单上传医院协友系统失败:接口无返回内容,fundId={}", serviceFund.getId());
            return false;
        }
        JSONObject jsonObject = null;
        try {
            jsonObject = JSONObject.parseObject(strRes);
        } catch (Exception e) {
            log.error("费用审批单上传医院协友系统失败:返回内容无法解析,fundId={},strRes={}",
                    serviceFund.getId(), strRes, e);
            return false;
        }
        if (jsonObject == null) {
            log.error("费用审批单上传医院协友系统失败:返回内容为空,fundId={},strRes={}",
                    serviceFund.getId(), strRes);
            return false;
        }
        String code = jsonObject.getString("code");
        if (code == null || !"0".equals(code)) {
            log.error("费用审批单上传医院协友系统失败:code={},fundId={},strRes={}",
                    code, serviceFund.getId(), strRes);
            return false;
        }
@@ -617,6 +835,10 @@
        List<Map<String, Object>> list = new ArrayList<>();
        List<Map<String, Object>> annexfilesList = new ArrayList<>();
        for (ServiceFunddetailShared serviceFunddetailShared : serviceFunddetailSharedList) {
            //附件处理
            String annexfiles = serviceFunddetailShared.getAnnexfiles();
            String invoicefiles = serviceFunddetailShared.getInvoicefiles();
            Map<String, Object> map = new HashMap<>();
            map.put("序号1", serviceFunddetailShared.getOrderno());
            map.put("费用项目", serviceFunddetailShared.getItemname());
@@ -624,15 +846,21 @@
            map.put("开户银行", serviceFunddetailShared.getDepositbank());
            map.put("卡号", serviceFunddetailShared.getBankcardno());
            map.put("收益人家属或专家", serviceFunddetailShared.getBeneficiaryname());
            map.put("税后金额", serviceFunddetailShared.getTaxamount());
            map.put("税后金额", serviceFunddetailShared.getTaxedamount());
            map.put("作废最终金额", null);
            String fpuuid = IdUtils.simpleUUID();
            map.put("发票附件", fpuuid);
            Long fpuuid = IdGeneratorUtils.nextId();
            map.put("发票附件", "");
            if (StringUtils.isNotEmpty(invoicefiles)) {
                map.put("发票附件", fpuuid);
            }
            map.put("发票识别", null);
            map.put("识别人", null);
            map.put("税额", null);
            String qtuuid = IdUtils.simpleUUID();
            map.put("其他附件", qtuuid);
            map.put("税额", serviceFunddetailShared.getTaxamount());
            long qtuuid = IdGeneratorUtils.nextId();
            map.put("其他附件", "");
            if (StringUtils.isNotEmpty(annexfiles)) {
                map.put("其他附件", qtuuid);
            }
            map.put("项目编码", serviceFunddetailShared.getItemcode());
            map.put("预算项目", null);
            map.put("贷方科目", null);
@@ -642,9 +870,6 @@
            map.put("费用说明", null);
            list.add(map);
            //附件处理
            String annexfiles = serviceFunddetailShared.getAnnexfiles();
            String invoicefiles = serviceFunddetailShared.getInvoicefiles();
            int i = 0;
            if (StringUtils.isNotEmpty(annexfiles)) {
@@ -676,48 +901,86 @@
    }
    private Map<String, Object> getformmain_0831(ServiceFundShared serviceFundShared) {
    private Map<String, Object> getformmain_0831(ServiceFund serviceFund) {
        ServiceFundflow serviceFundflow = new ServiceFundflow();
        serviceFundflow.setFundid(serviceFund.getId());
        serviceFundflow.setFundtype(2);
        List<ServiceFundflow> serviceFundflows = serviceFundflowService.queryList(serviceFundflow);
        Map<String, Object> formmain_0831 = new HashMap<>();
        formmain_0831.put("捐献者姓名", serviceFundShared.getDonorname());
        formmain_0831.put("报销人员", serviceFundShared.getUsername());
        formmain_0831.put("业务区域", serviceFundShared.getDeptmentname());
        formmain_0831.put("经手人", serviceFundShared.getUsername());
        formmain_0831.put("填表时间", serviceFundShared.getApplyTime());
        formmain_0831.put("报销金额合计", serviceFundShared.getPretaxcost());
        formmain_0831.put("捐献者姓名", serviceFund.getDonorname());
        formmain_0831.put("报销人员", serviceFund.getUsername());
        formmain_0831.put("业务区域", serviceFund.getDeptmentname());
        formmain_0831.put("经手人", serviceFund.getUsername());
        formmain_0831.put("填表时间", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(serviceFund.getApplyTime()));
        formmain_0831.put("报销金额合计", serviceFund.getPretaxcost());
        formmain_0831.put("上传附件", null);
        formmain_0831.put("备注", null);
        formmain_0831.put("财务审批", serviceFundShared.getFinancechecher());
        formmain_0831.put("财务部负责人审批", serviceFundShared.getFinancedirector());
        formmain_0831.put("办公室主任审批", serviceFundShared.getOfficedirector());
        formmain_0831.put("业务副院长审批", serviceFundShared.getBusvicepresident());
        formmain_0831.put("财务副院长审批", serviceFundShared.getFinvicepresident());
        formmain_0831.put("中心负责人审批", serviceFundShared.getOpochecker());
        formmain_0831.put("支付方式", serviceFundShared.getZffs());
        formmain_0831.put("组长", null);
        formmain_0831.put("审批人员", null);
        formmain_0831.put("支付日期", serviceFundShared.getRiqi());
        formmain_0831.put("财务审批", null);
        formmain_0831.put("财务部负责人审批", getLastApprovalInfo(serviceFundflows, serviceFund.getFinancedirector()));
//        formmain_0831.put("办公室主任审批", "办公室主任审批", "审批人:吴志强 & 审批时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " & 审批结果:通过");
        if (serviceFund.getBackflowlevel() == 3)
            formmain_0831.put("办公室主任审批", "审批人:吴志强 & 审批时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " & 审批结果:通过");
        else formmain_0831.put("办公室主任审批", getLastApprovalInfo(serviceFundflows, "吴志强"));
        formmain_0831.put("业务副院长审批", serviceFund.getBusvicepresident());
        formmain_0831.put("财务副院长审批", serviceFund.getFinvicepresident());
        formmain_0831.put("中心负责人审批", serviceFund.getOpochecker());
        formmain_0831.put("支付方式", serviceFund.getZffs());
        String lastApprovalInfo = getLastApprovalInfo(serviceFundflows, serviceFund.getManagername());
        formmain_0831.put("组长", lastApprovalInfo.contains("吴志强") ? null : lastApprovalInfo);
        formmain_0831.put("审批人员", StringUtils.isEmpty(getLastApprovalInfo(serviceFundflows, serviceFund.getFinancechecher())) ? "陈慕华" : getLastApprovalInfo(serviceFundflows, serviceFund.getFinancechecher()));
        formmain_0831.put("支付日期", serviceFund.getRiqi());
        formmain_0831.put("识别人-作废", null);
        formmain_0831.put("财务审批签字", serviceFundShared.getFinancedirector());
        formmain_0831.put("财务部负责人签字", serviceFundShared.getFinancedirector());
        formmain_0831.put("表达类型", null);
        formmain_0831.put("税前金额合计", serviceFundShared.getPretaxcost());
        formmain_0831.put("税额合计", serviceFundShared.getPretaxcost() - serviceFundShared.getTaxedcost());
        formmain_0831.put("财务审批签字", serviceFund.getFinancedirector());
        formmain_0831.put("财务部负责人签字", serviceFund.getFinancedirector());
        formmain_0831.put("表达类型", StringUtils.isEmpty(serviceFund.getApplytype()) ? null : ApplyTypeEnum.getDescByCode(serviceFund.getApplytype()));
        formmain_0831.put("税前金额合计", serviceFund.getPretaxcost());
        formmain_0831.put("税额合计", serviceFund.getPretaxcost() - serviceFund.getTaxedcost());
        formmain_0831.put("表单编号1", null);
        formmain_0831.put("编码", null);
        formmain_0831.put("CIF账套配置1", null);
        formmain_0831.put(" 院区", null);
        formmain_0831.put("是否支付", serviceFundShared.getIsdistribute());
        formmain_0831.put("是否支付", serviceFund.getIsdistribute());
        formmain_0831.put("凭证号", null);
        formmain_0831.put("银行回单", null);
        formmain_0831.put("OFD", null);
        formmain_0831.put("表单附件", null);
        formmain_0831.put("现金流量分析", null);
        formmain_0831.put("凭证类别", null);
        formmain_0831.put("税后金额合计", serviceFundShared.getTaxedcost());
        formmain_0831.put("税后金额合计", serviceFund.getTaxedcost());
        formmain_0831.put("历史审批记录", null);
        formmain_0831.put("表单编号", serviceFundShared.getBh());
        formmain_0831.put("表单编号", serviceFund.getId());
        formmain_0831.put("历史审批单查询", null);
        return formmain_0831;
    }
    public String getLastApprovalInfo(List<ServiceFundflow> serviceFundflows, String managerName) {
        log.info("---------------serviceFundflows的入参为:{},managerName的值为:{}", serviceFundflows, managerName);
        if (StringUtils.isEmpty(managerName)) return "";
        if (CollectionUtils.isEmpty(serviceFundflows)) {
            //如果是最后一个人审批,这个时候可能flow里还没有生成进去
            SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return "审批人:" + managerName + " & 审批时间:" + sd.format(new Date()) + " & 审批结果:通过";
        }
        //去一下空格
        String mn = managerName.trim();
        Optional<ServiceFundflow> lastApproval = serviceFundflows.stream().filter(flow -> mn.trim().contains(flow.getCheckusername())).max(Comparator.comparing(ServiceFundflow::getCreateTime));
        if (lastApproval.isPresent()) {
            ServiceFundflow flow = lastApproval.get();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (flow.getCheckTime() == null) {
                flow.setCheckTime(new Date());
            }
            String formattedTime = sdf.format(flow.getCheckTime());
            return "审批人:" + managerName + " & 审批时间:" + formattedTime + " & 审批结果:通过";
        }
        return "";
    }
    @Override
@@ -758,13 +1021,12 @@
            serviceFunddetailShareds.get(i).setId(null);
            //数据发送给财务
            try {
                if (!active.equals("druid")) uploadOAFileAndUpdateDb(serviceFunddetailShareds.get(i));
                if (isUploadOaEnabled()) uploadOAFileAndUpdateDb(serviceFunddetailShareds.get(i));
            } catch (Exception e) {
                e.printStackTrace();
                log.error("Exception中入参的ID为:{},异常信息为 : {}", id, e.getMessage());
                log.error("费用附件上传医院协友系统失败:单据id={}(本次报销单上传整体失败,审批不生效)", id, e);
                if (id != null) {
                    Boolean aBoolean = sharedService.delfundsharedInfoById(null, id);
                    log.error("fund2分享表里的数据是否删除成功:{}", aBoolean);
                    log.error("已回滚分享表数据:{}", aBoolean);
                }
                return false;
            }
@@ -1294,8 +1556,23 @@
    }
    @Override
    public ExpertFeeCheckResult validateExpertFee(ServiceFundVO serviceFundVO) {
        return expertFeeValidateService.validateBeforeSave(serviceFundVO);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addOrUpdateNew(ServiceFundVO serviceFundVO) {
        // 专家劳务费:保存前校验 9 条费用控制规则(同一案例累计)
        ExpertFeeCheckResult expertFeeResult = expertFeeValidateService.validateBeforeSave(serviceFundVO);
        if (expertFeeResult.hasError()) {
            throw new BaseException(expertFeeResult.errorMessage());
        }
        if (expertFeeResult.hasWarning()) {
            // 规则 5、6 仅提示,不阻断保存;前端单独取用提示文案
            log.warn("专家劳务费保存校验提示:{}", expertFeeResult.warningMessage());
        }
        Long id = null;
        //将数据保存到fund表
        serviceFundVO.setUploadStates(0);
@@ -1357,10 +1634,9 @@
            return null;
        }
        //总税前
        Double pretaxcosts = 0.00;
        //总税后
        Double taxedcosts = 0.00;
        //总税前、总税后(金额累加用 BigDecimal,避免浮点尾差)
        BigDecimal pretaxcosts = BigDecimal.ZERO;
        BigDecimal taxedcosts = BigDecimal.ZERO;
        for (ServiceFunddetailVO serviceFunddetailVO : serviceFunddetails) {
            serviceFunddetailVO.setFundid(id);
@@ -1369,13 +1645,18 @@
            if (!performance.isEmpty()) {
                Double amount = performance.get("amount");
                Double taxedamount = performance.get("taxedamount");
                pretaxcosts = pretaxcosts + amount;
                taxedcosts = taxedcosts + taxedamount;
                if (amount != null) {
                    pretaxcosts = pretaxcosts.add(BigDecimal.valueOf(amount));
                }
                if (taxedamount != null) {
                    taxedcosts = taxedcosts.add(BigDecimal.valueOf(taxedamount));
                }
            }
            serviceFundVO.setPretaxcost(pretaxcosts);
            serviceFundVO.setTaxedcost(taxedcosts);
            updateById(serviceFundVO);
        }
        // 合计在循环结束后统一回写,原来写在循环内会每行都 UPDATE 一次,且中间值被反复覆盖
        serviceFundVO.setPretaxcost(pretaxcosts.doubleValue());
        serviceFundVO.setTaxedcost(taxedcosts.doubleValue());
        updateById(serviceFundVO);
        Map map = new HashMap();
        map.put("fundId", id);
        return map;
@@ -1530,18 +1811,19 @@
    int uploadOAFileAndUpdateDb(ServiceFunddetailShared remShare) throws Exception {
        //上传OA文件
        String strUrl = "http://129.88.242.39:8899/seeyon/rest/token";
        //上传文件成功后,去更新相关的数据库
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userName", "opo");
        map.put("password", "4126407a-9821-4874-be41-6568abd6dbe5");
        map.put("loginName", "demo3");
//        String strUrl = "http://129.88.242.39:8899/seeyon/rest/token";
//        //上传文件成功后,去更新相关的数据库
//        Map<String, Object> map = new HashMap<String, Object>();
//        map.put("userName", "opo");
//        map.put("password", "4126407a-9821-4874-be41-6568abd6dbe5");
//        map.put("loginName", "demo3");
//
//        JSONObject jsonObj = new JSONObject(map);
//
//        System.out.println("uploadOAFileAndUpdateDb + jsonObject" + jsonObj.toString() + "\r\n" + jsonObj.toJSONString());
//        String strRes = HttpClientKit.postOpr(strUrl, jsonObj.toString());//
        String strRes = getToken();
        JSONObject jsonObj = new JSONObject(map);
        System.out.println("uploadOAFileAndUpdateDb + jsonObject" + jsonObj.toString() + "\r\n" + jsonObj.toJSONString());
        String strRes = HttpClientKit.postOpr(strUrl, jsonObj.toString());//
        //String strRes = HttpClientKit.postMsg(strUrl,jsonObj);//得到返回的token?
        JSONObject json1 = JSONObject.parseObject(strRes);
        strRes = json1.get("id").toString();
@@ -1565,6 +1847,22 @@
        return 0;
    }
    private String getToken() {
        //上传OA文件
        String strUrl = "http://129.88.242.39:8899/seeyon/rest/token";
        //上传文件成功后,去更新相关的数据库
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userName", "opo");
        map.put("password", "4126407a-9821-4874-be41-6568abd6dbe5");
        map.put("loginName", "OPO系统");
        JSONObject jsonObj = new JSONObject(map);
        System.out.println("uploadOAFileAndUpdateDb + jsonObject" + jsonObj.toString() + "\r\n" + jsonObj.toJSONString());
        String strRes = HttpClientKit.postOpr(strUrl, jsonObj.toString());
        return strRes;
    }
    private Integer uploadFile(String filePath, String strFUrl, List<RbDetailFile> parseArray2, List<RbDetailFile> parseArray, ServiceFunddetailShared remShare, String flag) throws Exception {
        if (!CollectionUtils.isEmpty(parseArray)) {
@@ -1573,10 +1871,18 @@
                log.info("filePath的修改:{}", filePath);
                String url = rbDetailFile.getUrl();
                //file用的是绝对位置
                String substring = url.substring(url.indexOf("/profile/upload") + "/profile/upload".length());
                // 2026-10-09:附件地址解析加固,避免 url 异常/文件缺失时抛 NPE 导致看不到失败原因
                int profileIdx = url == null ? -1 : url.indexOf("/profile/upload");
                if (profileIdx < 0) {
                    throw new ServiceException("附件地址格式不正确(缺少 /profile/upload),无法上传协友:" + url);
                }
                String substring = url.substring(profileIdx + "/profile/upload".length());
//            String strFile = rbDetailFile.getUrl().replace(filePath, "/profile/upload");
                System.out.println("fund服务的filePath + substring: " + filePath + substring);
                File filetest = new File(filePath + substring);
                if (!filetest.exists()) {
                    throw new ServiceException("附件文件在服务器上不存在,无法上传协友:" + filetest.getAbsolutePath());
                }
                String struploadResult = HttpClientKit.sendPostWithFile(filetest, strFUrl);
                log.info("第三方传回的数据: {}", struploadResult);
@@ -1675,7 +1981,8 @@
    }
    public void sendMeg(ServiceProcessVO serviceProcessVO, String phone) {
    public void sendMeg(ServiceProcessVO serviceProcessVO, String phone,
                        List<ConcurrentHashMap<String, Object>> contentList) {
        //记录操作记录
        ServiceFundflow serviceFundflow = new ServiceFundflow();
@@ -1683,27 +1990,25 @@
        serviceFundflow.setUpdateBy(serviceProcessVO.getCheckusername());
        serviceFundflow.setCheckusername(serviceProcessVO.getCheckusername());
        serviceFundflow.setCreateTime(new Date());
        serviceFundflow.setCheckTime(new Date());
        serviceFundflow.setUpdateTime(new Date());
        serviceFundflow.setFlowcontent(serviceProcessVO.getFlowcontent());
        serviceFundflow.setFlowconclusion(serviceProcessVO.getFlowconclusion());
        if (serviceProcessVO.getApplytype() == "0") serviceFundflow.setFundtype(1);
        if (serviceProcessVO.getApplytype() == "1") serviceFundflow.setFundtype(2);
        serviceFundflow.setFlowconclusion(StringUtils.isNotEmpty(serviceProcessVO.getFlowconclusion()) ? Integer.valueOf(serviceProcessVO.getFlowconclusion()) : null);
        if (serviceProcessVO.getApplytype().equals("0")) serviceFundflow.setFundtype(1);
        if (serviceProcessVO.getApplytype().equals("1")) serviceFundflow.setFundtype(2);
        serviceFundflow.setFlowlevel(100);
        serviceFundflow.setApplytype(serviceProcessVO.getApplytype());
        serviceFundflow.setFundid(serviceProcessVO.getBackCode());
        serviceFundflow.setFundid(StringUtils.isNotEmpty(serviceProcessVO.getBackCode()) ? Long.valueOf(serviceProcessVO.getBackCode()) : null);
        fundflowService.save(serviceFundflow);
        ArrayList<ConcurrentHashMap<String, Object>> contentList = new ArrayList<>();
        ConcurrentHashMap map = new ConcurrentHashMap();
        map.put("审批人:", serviceProcessVO.getCheckusername());
        map.put("审批时间:", serviceProcessVO.getCheckTime());
        map.put("意见:", serviceProcessVO.getFlowcontent());
        contentList.add(map);
        DingTalkReqVo dingTalkReqVo = new DingTalkReqVo();
        dingTalkReqVo.setTitle("财务系统信息");
        dingTalkReqVo.setNumber(phone);
        dingTalkReqVo.setContents(contentList);
        log.info("钉钉发送消息:{}", dingTalkReqVo);
        dingTalkService.sendNotification(dingTalkReqVo);
        try {
            DingTalkReqVo dingTalkReqVo = new DingTalkReqVo();
            dingTalkReqVo.setTitle(FundNotifyMessageBuilder.TITLE);
            dingTalkReqVo.setNumber(phone);
            dingTalkReqVo.setContents(contentList);
            log.info("钉钉发送消息:{}", dingTalkReqVo);
            dingTalkService.sendNotification(dingTalkReqVo);
        } catch (Exception e) {
            log.error("报销审批钉钉消息发送失败,不影响主流程", e);
        }
    }
}