Преглед изворни кода

Merge branch 'fu-dev' of uskycloud/usky-modules into server-165

fuyuchuan пре 9 месеци
родитељ
комит
a73765af43

+ 13 - 0
service-iot/service-iot-api/src/main/java/com/usky/iot/RemotePmService.java

@@ -0,0 +1,13 @@
+package com.usky.iot;
+
+
+import com.usky.iot.factory.RemotePmFactory;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@FeignClient(contextId = "remoteIotService", value = "service-iot" , fallbackFactory = RemotePmFactory.class)
+public interface RemotePmService {
+
+    @GetMapping("/executeTimedSending")
+    void executeTimedSending();
+}

+ 34 - 0
service-iot/service-iot-api/src/main/java/com/usky/iot/factory/RemotePmFactory.java

@@ -0,0 +1,34 @@
+package com.usky.iot.factory;
+
+import com.usky.common.core.exception.FeignBadRequestException;
+import com.usky.iot.RemotePmService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.openfeign.FallbackFactory;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 用户服务降级处理
+ *
+ * @author ruoyi
+ */
+@Component
+public class RemotePmFactory implements FallbackFactory<RemotePmService>
+{
+    private static final Logger log = LoggerFactory.getLogger(RemotePmFactory.class);
+
+    @Override
+    public RemotePmService create(Throwable throwable)
+    {
+        log.error("用户服务调用失败:{}", throwable.getMessage());
+        return new RemotePmService()
+        {
+            @Override
+            public void executeTimedSending() {
+                throw new FeignBadRequestException(500,"公告报告定时发送异常"+throwable.getMessage());
+            }
+
+        };
+    }
+}

+ 27 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/api/PmTimedSendingApi.java

@@ -0,0 +1,27 @@
+package com.usky.iot.controller.api;
+
+import com.usky.iot.RemotePmService;
+import com.usky.iot.service.PmWorkReportService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ *  数据统一查询 前端控制器
+ * </p>
+ *
+ */
+@RestController
+public class PmTimedSendingApi implements RemotePmService {
+
+    @Autowired
+    private PmWorkReportService pmWorkReportService;
+
+    @Override
+    public void executeTimedSending() {
+        LocalDateTime now = LocalDateTime.now();
+        pmWorkReportService.timedSending(now);
+    }
+}

+ 14 - 1
service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/web/PmWorkReportController.java

@@ -1,6 +1,7 @@
 package com.usky.iot.controller.web;
 
 
+import com.aliyuncs.exceptions.ClientException;
 import com.usky.common.core.bean.ApiResult;
 import com.usky.iot.domain.PmWorkReport;
 import com.usky.iot.service.PmProjectService;
@@ -8,6 +9,7 @@ import com.usky.iot.service.PmWorkReportService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.time.LocalDateTime;
 import java.util.List;
 import java.util.Map;
 
@@ -49,7 +51,7 @@ public class PmWorkReportController {
      * @param
      */
     @PostMapping("/add")
-    public void add(@RequestBody PmWorkReport pmWorkReport) {
+    public void add(@RequestBody PmWorkReport pmWorkReport)  throws ClientException {
         pmWorkReportService.addReport(pmWorkReport);
     }
 
@@ -62,4 +64,15 @@ public class PmWorkReportController {
     public ApiResult<List<Map<String, Object>>> weekWork() {
         return ApiResult.success(pmWorkReportService.countTime());
     }
+
+    /**
+     * 测试定时发送
+     *
+     * @param
+     */
+    @GetMapping("/ScheduledTasks")
+    public void add(){
+        LocalDateTime now = LocalDateTime.now();
+        pmWorkReportService.timedSending(now);
+    }
 }

+ 18 - 1
service-iot/service-iot-biz/src/main/java/com/usky/iot/domain/PmWorkReport.java

@@ -11,6 +11,7 @@ import java.time.LocalDateTime;
 import java.io.Serializable;
 import java.util.List;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.*;
 import org.springframework.data.annotation.Transient;
 
@@ -112,7 +113,23 @@ public class PmWorkReport implements Serializable {
     private Integer readFlag;
 
     /**
-     * 是否发送钉钉 默认:0,否;1:是
+     * 是否发送钉钉 (默认:0,否;1:是)
      */
     private Integer sendDingTalk;
+
+    /**
+     * 定时时间
+     */
+    //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime timingTime;
+
+    /**
+     * 报告状态(默认1,0:保存状态;1:发送状态)
+     */
+    private Integer reportStatus;
+
+    /**
+     * 是否定时(默认0:否,1:是)
+     */
+    private Integer isRegularlySend;
 }

+ 5 - 4
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/PmWorkReportService.java

@@ -1,9 +1,11 @@
 package com.usky.iot.service;
 
+import com.aliyuncs.exceptions.ClientException;
 import com.usky.iot.domain.PmWorkContent;
 import com.usky.iot.domain.PmWorkReport;
 import com.usky.common.mybatis.core.CrudService;
 
+import java.time.LocalDateTime;
 import java.util.List;
 import java.util.Map;
 
@@ -30,7 +32,7 @@ public interface PmWorkReportService extends CrudService<PmWorkReport> {
      * 新增、编辑工作报告
      * @param pmWorkReport 工作报告
      */
-    void addReport(PmWorkReport pmWorkReport);
+    void addReport(PmWorkReport pmWorkReport)  throws ClientException;
 
 
     /**
@@ -40,8 +42,7 @@ public interface PmWorkReportService extends CrudService<PmWorkReport> {
     List<Map<String, Object>> countTime();
 
     /**
-     * 同步钉钉
-     * @param workReport 工作报告
+     * 定时发送
      */
-    void sendDingTalkDailyReport(PmWorkReport workReport, List<PmWorkContent> workContents);
+    void timedSending(LocalDateTime time);
 }

+ 290 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/config/DingTalkAndMessage.java

@@ -0,0 +1,290 @@
+package com.usky.iot.service.config;
+
+import com.alibaba.fastjson.JSONObject;
+import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse;
+import com.aliyun.tea.TeaException;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiReportCreateRequest;
+import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;
+import com.dingtalk.api.response.OapiReportCreateResponse;
+import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.usky.common.core.bean.ApiResult;
+import com.usky.common.security.utils.SecurityUtils;
+import com.usky.iot.constant.dingTalkConstant;
+import com.usky.iot.domain.MceMbuser;
+import com.usky.iot.domain.PmWorkContent;
+import com.usky.iot.domain.PmWorkReport;
+import com.usky.iot.mapper.MceMbuserMapper;
+import com.usky.iot.mapper.PmWorkReportMapper;
+import com.usky.iot.mapper.SysUserMapper;
+import com.usky.system.RemoteMceService;
+import com.usky.system.domain.SysUser;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.Async;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @description:TODO
+ * @author: fu
+ * @create: 2024-07-30 10:32
+ */
+@Slf4j
+@Configuration
+public class DingTalkAndMessage {
+
+    private static final String INFO_TITLE = "报告提醒";
+    private static final String INFO_CONTENT = "的报告";
+    private static final int INFO_TYPE = 5;
+
+    @Autowired
+    private RemoteMceService remoteMceService;
+
+    @Autowired
+    private MceMbuserMapper mceMbuserMapper;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Autowired
+    private PmWorkReportMapper pmWorkReportMapper;
+
+    /**
+     * 指定请求
+     *
+     * @return
+     * @throws Exception
+     */
+    public static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception {
+        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        config.method = "POST";
+        return new com.aliyun.dingtalkoauth2_1_0.Client(config);
+    }
+
+    /**
+     * 获取钉钉企业内部AccessToken
+     *
+     * @return
+     * @throws Exception
+     */
+    public String getDingTalkToken() {
+        GetAccessTokenResponse responseBody = new GetAccessTokenResponse();
+        com.aliyun.dingtalkoauth2_1_0.Client client = null;
+        try {
+            client = createClient();
+        } catch (Exception e) {
+            log.error("获取钉钉token异常:" + e);
+        }
+        com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest getAccessTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest()
+                .setAppKey(dingTalkConstant.DING_TALK_CLIENT_ID)
+                .setAppSecret(dingTalkConstant.DING_TALK_CLIENT_SECRET);
+        try {
+            responseBody = client.getAccessToken(getAccessTokenRequest);
+        } catch (TeaException err) {
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                log.error("获取钉钉token异常:" + err.code + err.message);
+            }
+        } catch (Exception _err) {
+            TeaException err = new TeaException(_err.getMessage(), _err);
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                log.error("获取钉钉token异常:" + err.code + err.message);
+            }
+        }
+        return responseBody.getBody().accessToken;
+    }
+
+    /**
+     * 获取钉钉userId
+     *
+     * @param userId 平台userid
+     * @return
+     */
+    public String getDingTalkUserId(Long userId) {
+        String dingTalkId = "";
+        LambdaQueryWrapper<MceMbuser> dingTalkQuery = Wrappers.lambdaQuery();
+        dingTalkQuery.select(MceMbuser::getDingTalkId, MceMbuser::getUserId)
+                .eq(MceMbuser::getUserId, userId);
+        MceMbuser mceMbuser = mceMbuserMapper.selectOne(dingTalkQuery);
+        if (mceMbuser != null) {
+            String dingId = mceMbuser.getDingTalkId();
+            if (StringUtils.isNotBlank(dingId)) {
+                return mceMbuser.getDingTalkId();
+            }
+        }
+        LambdaQueryWrapper<SysUser> phoneQuery = Wrappers.lambdaQuery();
+        phoneQuery.select(SysUser::getPhonenumber, SysUser::getUserName)
+                .eq(SysUser::getUserId, userId);
+        SysUser user = sysUserMapper.selectOne(phoneQuery);
+        String mobile = user.getPhonenumber();
+        try {
+            String accessToken = getDingTalkToken();
+            DingTalkClient client = new DefaultDingTalkClient(dingTalkConstant.DING_TALK_USERID_URL);
+            OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
+            req.setMobile(mobile);
+            OapiV2UserGetbymobileResponse rsp = client.execute(req, accessToken);
+            ObjectMapper objectMapper = new ObjectMapper();
+            JsonNode rootNode = objectMapper.readTree(rsp.getBody());
+            JsonNode resultNode = rootNode.get("result");
+            dingTalkId = resultNode.get("userid").asText();
+        } catch (Exception e) {
+            log.error("获取钉钉用户ID失败", e);
+        }
+        if (mceMbuser != null) {
+            mceMbuser.setDingTalkId(dingTalkId);
+            mceMbuser.setUpdateBy(SecurityUtils.getUsername());
+            mceMbuser.setUpdateTime(LocalDateTime.now());
+            mceMbuserMapper.update(mceMbuser, dingTalkQuery);
+        } else {
+            MceMbuser mbuser = new MceMbuser();
+            mbuser.setDingTalkId(dingTalkId);
+            mbuser.setPhone(mobile);
+            mbuser.setUserId(userId);
+            mbuser.setCreateBy(user.getUserName());
+            mbuser.setCreateTime(LocalDateTime.now());
+            mceMbuserMapper.insert(mbuser);
+        }
+        return dingTalkId;
+    }
+
+    @Async("asyncServiceExecutor")//异步发送
+    public void sendDingTalkDailyReport(PmWorkReport workReport, List<PmWorkContent> workContents) {
+        String userName = workReport.getCreateBy();
+        log.info(userName + "的工作报告开始发送钉钉-----------------------------------");
+        String ccToStr = workReport.getCcTo();
+        String[] items = ccToStr.split(",");
+        try {
+            List<Long> userIds = new ArrayList<>();
+            for (String item : items) {
+                long number = Long.parseLong(item.trim());
+                userIds.add(number);
+            }
+            List<String> ccTo = new ArrayList<>();
+            for (Long userId : userIds) {
+                String dingTalkUserId = getDingTalkUserId(userId);
+                ccTo.add(dingTalkUserId);
+            }
+            String reportCoordinateWork = workReport.getCoordinateWork();
+            String reportTomorrowPlan = workReport.getTomorrowPlan();
+            String coordinateWork1 = "-";
+            String tomorrowPlan1 = "-";
+            if (reportCoordinateWork != null && reportCoordinateWork != "") {
+                coordinateWork1 = reportCoordinateWork;
+            }
+            if (reportTomorrowPlan != null && reportTomorrowPlan != "") {
+                tomorrowPlan1 = reportTomorrowPlan;
+            }
+
+            StringBuilder contentBuilder = new StringBuilder();
+            for (PmWorkContent content : workContents) {
+                String projectName = content.getProjectName();
+                BigDecimal workTime = content.getWorkTime();
+                String workContent = content.getWorkContent();
+                StringBuilder markdown = new StringBuilder();
+                markdown.append("#### ").append(projectName).append(" ").append(workTime).append("h\n\n");
+                markdown.append("<span style=\"font-size: 8px;\">").append(workContent).append("\n").append("</span>");
+                contentBuilder.append(markdown);
+            }
+            String completedWork = contentBuilder.toString();
+            DingTalkClient client = new DefaultDingTalkClient(dingTalkConstant.DING_TALK_CREATE_DAILY_REPORT_URL);
+            OapiReportCreateRequest req = new OapiReportCreateRequest();
+            OapiReportCreateRequest.OapiCreateReportParam obj1 = new OapiReportCreateRequest.OapiCreateReportParam();
+            List<OapiReportCreateRequest.OapiReportContentVo> list3 = new ArrayList<>();
+            OapiReportCreateRequest.OapiReportContentVo completedWorkD = new OapiReportCreateRequest.OapiReportContentVo();
+            completedWorkD.setSort(0L);
+            completedWorkD.setType(1L);
+            completedWorkD.setContentType(dingTalkConstant.DING_TALK_DAILY_REPORT_CONTENT_TYPE);
+            completedWorkD.setContent(completedWork);
+            completedWorkD.setKey(dingTalkConstant.DING_TALK_DAILY_REPORT_COMPLETED_WORK);
+            list3.add(completedWorkD);
+            OapiReportCreateRequest.OapiReportContentVo tomorrowPlan = new OapiReportCreateRequest.OapiReportContentVo();
+            tomorrowPlan.setSort(1L);
+            tomorrowPlan.setType(1L);
+            tomorrowPlan.setContentType(dingTalkConstant.DING_TALK_DAILY_REPORT_CONTENT_TYPE);
+            tomorrowPlan.setContent(tomorrowPlan1);
+            tomorrowPlan.setKey(dingTalkConstant.DING_TALK_DAILY_REPORT_TOMORROW_PLAN);
+            list3.add(tomorrowPlan);
+            OapiReportCreateRequest.OapiReportContentVo coordinateWork = new OapiReportCreateRequest.OapiReportContentVo();
+            coordinateWork.setSort(2L);
+            coordinateWork.setType(1L);
+            coordinateWork.setContentType(dingTalkConstant.DING_TALK_DAILY_REPORT_CONTENT_TYPE);
+            coordinateWork.setContent(coordinateWork1);
+            coordinateWork.setKey(dingTalkConstant.DING_TALK_DAILY_REPORT_COORDINATE_WORK);
+            list3.add(coordinateWork);
+            obj1.setContents(list3);
+            obj1.setToUserids(ccTo);
+            obj1.setTemplateId(dingTalkConstant.DING_TALK_DAILY_REPORT_TEMPLATE_ID);
+            obj1.setToChat(dingTalkConstant.DING_TALK_DAILY_REPORT_TO_CHAT);
+            obj1.setDdFrom(dingTalkConstant.DING_TALK_CORP_ID);
+            obj1.setUserid(getDingTalkUserId(workReport.getSubmitterId()));
+            //obj1.setToCids(dingTalkConstant.DING_TALK_DAILY_REPORT_TO_CIDS);//发送到群,群id
+            req.setCreateReportParam(obj1);
+            OapiReportCreateResponse rsp = client.execute(req, getDingTalkToken());
+            if (rsp.isSuccess()) {
+                log.info("钉钉报告发送成功");
+                workReport.setReportStatus(1);
+                pmWorkReportMapper.updateById(workReport);
+            } else {
+                log.error("钉钉报告发送失败: " + rsp.getErrmsg());
+            }
+        } catch (Exception e) {
+            log.error("钉钉报告发送消息时发生异常", e);
+        }
+        log.info(userName + "的工作报告发送钉钉结束-----------------------------------");
+    }
+
+
+    @Async("asyncServiceExecutor")
+    public void sendAsyncMessage(PmWorkReport newReport) {
+        String username = newReport.getCreateBy();
+        Long submitterId = newReport.getSubmitterId();
+        log.info(username + "的工作报告开始发送消息中心-----------------------------------");
+        List<Long> userId = new ArrayList<>();
+        if (!newReport.getCcTo().isEmpty()) {
+            userId = Optional.ofNullable(newReport.getCcTo())
+                    .map(ccTo -> Arrays.stream(ccTo.split(","))
+                            .map(Long::parseLong)
+                            .collect(Collectors.toList()))
+                    .orElse(Collections.emptyList());
+        }
+        LambdaQueryWrapper<SysUser> nickNameQuery = Wrappers.lambdaQuery();
+        nickNameQuery.select(SysUser::getNickName)
+                .eq(SysUser::getUserId, submitterId);
+        SysUser nickName = sysUserMapper.selectOne(nickNameQuery);
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("infoTitle", INFO_TITLE);
+        jsonObject.put("infoContent", nickName + INFO_CONTENT);
+        jsonObject.put("infoType", INFO_TYPE);
+        jsonObject.put("id", newReport.getId());
+        jsonObject.put("infoTypeName", INFO_TITLE);
+        if (userId != null && !userId.isEmpty()) {
+            jsonObject.put("userIds", userId);
+        }
+        try {
+            // 推送消息中心
+            ApiResult<Void> voidApiResult = remoteMceService.addMce(jsonObject.toString());
+
+            if (voidApiResult.isSuccess()) {
+                log.info("报告消息发送成功!");
+            } else {
+                log.error("报告消息发送失败!");
+            }
+        } catch (Exception e) {
+            log.error("报告发送消息时发生异常", e);
+        }
+        log.info(username + "的工作报告发送消息中心完成-----------------------------------");
+    }
+}
+

+ 101 - 257
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmWorkReportServiceImpl.java

@@ -1,34 +1,22 @@
 package com.usky.iot.service.impl;
 
-import com.alibaba.fastjson.JSONObject;
-import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse;
-import com.aliyun.tea.TeaException;
+import com.aliyuncs.exceptions.ClientException;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.dingtalk.api.DefaultDingTalkClient;
-import com.dingtalk.api.DingTalkClient;
-import com.dingtalk.api.request.OapiReportCreateRequest;
-import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;
-import com.dingtalk.api.response.OapiReportCreateResponse;
-import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.usky.common.core.bean.ApiResult;
 import com.usky.common.core.exception.BusinessException;
 import com.usky.common.security.utils.SecurityUtils;
-import com.usky.iot.constant.dingTalkConstant;
 import com.usky.iot.domain.*;
 import com.usky.iot.mapper.*;
 import com.usky.iot.service.PmProjectService;
 import com.usky.iot.service.PmWorkContentService;
 import com.usky.iot.service.PmWorkReportService;
 import com.usky.common.mybatis.core.AbstractCrudService;
+import com.usky.iot.service.config.DingTalkAndMessage;
 import com.usky.iot.service.vo.PmProjectWorkTimeVo;
-import com.usky.system.RemoteMceService;
 import com.usky.system.domain.SysUser;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -39,7 +27,6 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.temporal.TemporalAdjusters;
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
 
@@ -55,9 +42,6 @@ import java.util.stream.Collectors;
 @Service
 public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMapper, PmWorkReport> implements PmWorkReportService {
 
-    private static final String INFO_TITLE = "报告提醒";
-    private static final String INFO_CONTENT = "的报告";
-    private static final int INFO_TYPE = 5;
 
     @Autowired
     private PmWorkContentMapper pmWorkContentMapper;
@@ -72,17 +56,11 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
     private PmWorkContentService pmWorkContentService;
 
     @Autowired
-    private RemoteMceService remoteMceService;
+    private DingTalkAndMessage dingTalkAndMessage;
 
     @Autowired
     private PmReceiveMapper pmReceiveMapper;
 
-    @Autowired
-    private MceMbuserMapper mceMbuserMapper;
-
-    @Autowired
-    private SysUserMapper sysUserMapper;
-
     /**
      * 获取时间内工作报告
      *
@@ -127,9 +105,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         }
         //固定返回七条数据,没有内容也要设置时间给前端渲染
         LambdaQueryWrapper<PmWorkReport> queryWrapperR = Wrappers.lambdaQuery();
-        queryWrapperR.select(PmWorkReport::getId, PmWorkReport::getReportDate, PmWorkReport::getSubmitDate, PmWorkReport::getUpdateTime,
-                PmWorkReport::getTomorrowPlan, PmWorkReport::getCoordinateWork, PmWorkReport::getCcTo, PmWorkReport::getSendDingTalk)
-                .eq(PmWorkReport::getSubmitterId, SecurityUtils.getUserId())
+        queryWrapperR.eq(PmWorkReport::getSubmitterId, SecurityUtils.getUserId())
                 .between(PmWorkReport::getReportDate, startDate1, endDate1)
                 .orderByAsc(PmWorkReport::getReportDate)
                 .apply(reportId != 0, "id = " + reportId);
@@ -218,13 +194,16 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
      */
     @Transactional
     @Override
-    public void addReport(PmWorkReport pmWorkReport) {
+    public void addReport(PmWorkReport pmWorkReport) throws ClientException {
         Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
         String userName = SecurityUtils.getUsername();
         Long userId = SecurityUtils.getUserId();
         Integer tenantId = SecurityUtils.getTenantId();
-        LocalDateTime dateTime = LocalDateTime.now();
         BigDecimal totalWorkTime = BigDecimal.ZERO; //计算总工时
+        LocalDateTime dateTime = LocalDateTime.now();
+        LocalDateTime timingTime = pmWorkReport.getTimingTime();
+        LocalDateTime currentTimePlusMinutes = dateTime.plusMinutes(5);
+
         if (pmWorkReport.getWorkContents() == null) {
             throw new BusinessException("报告内容不能为空,请检查!");
         }
@@ -266,6 +245,15 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
             newReport.setTenantId(tenantId);
             newReport.setTotalHours(totalWorkTime);
             newReport.setSendDingTalk(pmWorkReport.getSendDingTalk());
+            if (pmWorkReport.getIsRegularlySend() == 1 && timingTime != null) {
+                if (timingTime.isAfter(currentTimePlusMinutes)) {
+                    newReport.setIsRegularlySend(pmWorkReport.getIsRegularlySend());
+                    newReport.setTimingTime(timingTime);
+                    newReport.setReportStatus(0);
+                } else {
+                    throw new BusinessException("定时时间需提前至少五分钟!");
+                }
+            }
             try {
                 pmWorkReportMapper.insert(newReport);
 
@@ -282,6 +270,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
             //查出所有项目id对应项目名
             List<PmProject> project = pmProjectService.projectName(projectIds);
             //将项目名重新赋值
+            List<PmWorkContent> pmWorkContents = new ArrayList<>();
             for (PmWorkContent b : pmWorkReport.getWorkContents()) {
                 for (int c = 0; c < project.size(); c++) {
                     if (b.getProjectId() == project.get(c).getId()) {
@@ -301,45 +290,52 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
                 newContent.setDeptId(deptId);
                 newContent.setTenantId(tenantId);
                 pmWorkContentMapper.insert(newContent);
+                pmWorkContents.add(newContent);
             }
-            //推送消息中心
-            List<Long> ids = new ArrayList<>();
-            if (!newReport.getCcTo().isEmpty()) {
-                ids = Optional.ofNullable(newReport.getCcTo())
-                        .map(ccTo -> Arrays.stream(ccTo.split(","))
-                                .map(Long::parseLong)
-                                .collect(Collectors.toList()))
-                        .orElse(Collections.emptyList());
-            }
-            //sendAsyncMessage(newReport, ids);
-            List<Long> finalIds = ids;
-            CompletableFuture.runAsync(() -> {sendAsyncMessage(newReport, finalIds);});
-            //存入消息接收表
-            receiveMessages(ids, newReport.getId());
-            //是否同步钉钉
-            if (pmWorkReport.getSendDingTalk() == 1) {
-                //sendDingTalkDailyReport(pmWorkReport);
-                CompletableFuture.runAsync(() -> {
-                    sendDingTalkDailyReport(newReport, pmWorkReport.getWorkContents());
-                });
+            //抄送人不为空,非定时发送
+            if (StringUtils.isNotEmpty(pmWorkReport.getCcTo())) {
+                if (timingTime == null) {
+                    //推送消息中心
+                    dingTalkAndMessage.sendAsyncMessage(newReport);
+
+                    //是否同步钉钉
+                    if (pmWorkReport.getSendDingTalk() == 1) {
+                        dingTalkAndMessage.sendDingTalkDailyReport(newReport, pmWorkContents);
+                    }
+                }
+                //存入报告消息表
+                List<Long> longList = Arrays.stream(pmWorkReport.getCcTo().split(","))
+                        .map(Long::parseLong)
+                        .collect(Collectors.toList());
+                receiveMessages(longList, newReport.getId());
             }
         } else if (repeat.size() > 0) {
             PmWorkReport rp = new PmWorkReport();
             rp.setId(pmWorkReport.getId());
-            rp.setReportDate(pmWorkReport.getReportDate());
+            //rp.setReportDate(pmWorkReport.getReportDate());
             rp.setSubmitterId(pmWorkReport.getSubmitterId());
-            rp.setSubmitDate(pmWorkReport.getSubmitDate());
+            //rp.setSubmitDate(pmWorkReport.getSubmitDate());
             rp.setCcTo(pmWorkReport.getCcTo());
             rp.setCoordinateWork(pmWorkReport.getCoordinateWork());
             rp.setTomorrowPlan(pmWorkReport.getTomorrowPlan());
             rp.setCreateBy(pmWorkReport.getCreateBy());
-            rp.setCreateTime(pmWorkReport.getCreateTime());
-            rp.setUpdateTime(dateTime);
-            rp.setDeptId(pmWorkReport.getDeptId());
-            rp.setTenantId(pmWorkReport.getTenantId());
+            //rp.setCreateTime(pmWorkReport.getCreateTime());
+            //rp.setDeptId(pmWorkReport.getDeptId());
+            //rp.setTenantId(pmWorkReport.getTenantId());
             rp.setUpdateBy(userName);
             rp.setUpdateTime(dateTime);
             rp.setTotalHours(totalWorkTime);
+            if (pmWorkReport.getIsRegularlySend() == 1) {
+                if (timingTime != null && timingTime.isAfter(currentTimePlusMinutes)) {
+                    rp.setTimingTime(timingTime);
+                } else {
+                    throw new BusinessException("定时时间需大于五分钟!");
+                }
+            } else {
+                rp.setIsRegularlySend(0);
+            }
+            //rp.setReportStatus(pmWorkReport.getReportStatus());
+            rp.setSendDingTalk(pmWorkReport.getSendDingTalk());
             pmWorkReportMapper.updateById(rp);
             LambdaQueryWrapper<PmWorkContent> queryWrapper = Wrappers.lambdaQuery();
             queryWrapper.select(PmWorkContent::getReportId, PmWorkContent::getSubmitterId, PmWorkContent::getCreateBy, PmWorkContent::getCreateTime, PmWorkContent::getDeptId, PmWorkContent::getTenantId)
@@ -348,6 +344,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
             PmWorkContent f = pmWorkContentMapper.selectOne(queryWrapper);
             pmWorkContentService.deleteContent(pmWorkReport.getId());
             List<PmWorkContent> contents = pmWorkReport.getWorkContents();
+            List<PmWorkContent> contentsList = new ArrayList<>();
             for (PmWorkContent e : contents) {
                 e.setReportId(f.getReportId());
                 e.setUpdateBy(userName);
@@ -358,6 +355,12 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
                 e.setDeptId(f.getDeptId());
                 e.setTenantId(f.getTenantId());
                 pmWorkContentMapper.insert(e);
+                contentsList.add(e);
+            }
+            if (pmWorkReport.getSendDingTalk().equals(1)) {
+                dingTalkAndMessage.sendDingTalkDailyReport(rp, contentsList);
+                rp.setReportStatus(1);
+                pmWorkReportMapper.updateById(rp);
             }
         }
     }
@@ -384,31 +387,6 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         }
     }
 
-    @Async("asyncServiceExecutor")
-    public void sendAsyncMessage(PmWorkReport newReport, List<Long> userId) {
-        JSONObject jsonObject = new JSONObject();
-        jsonObject.put("infoTitle", INFO_TITLE);
-        jsonObject.put("infoContent", SecurityUtils.getLoginUser().getSysUser().getNickName() + INFO_CONTENT);
-        jsonObject.put("infoType", INFO_TYPE);
-        jsonObject.put("id", newReport.getId());
-        jsonObject.put("infoTypeName", INFO_TITLE);
-        if (userId != null && !userId.isEmpty()) {
-            jsonObject.put("userIds", userId);
-        }
-        // 推送消息中心
-        try {
-            ApiResult<Void> voidApiResult = remoteMceService.addMce(jsonObject.toString());
-
-            if (voidApiResult.isSuccess()) {
-                log.info("报告消息发送成功!");
-            } else {
-                log.error("报告消息发送失败!");
-            }
-        } catch (Exception e) {
-            log.error("发送消息时发生异常", e);
-        }
-    }
-
     @Override
     public List<Map<String, Object>> countTime() {
         int scale = 2;
@@ -493,185 +471,51 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         return returnList;
     }
 
-    /**
-     * 指定请求
-     *
-     * @return
-     * @throws Exception
-     */
-    public static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception {
-        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
-        config.protocol = "https";
-        config.regionId = "central";
-        config.method = "POST";
-        return new com.aliyun.dingtalkoauth2_1_0.Client(config);
-    }
-
-    /**
-     * 获取钉钉企业内部AccessToken
-     *
-     * @return
-     * @throws Exception
-     */
-    public String getDingTalkToken() {
-        GetAccessTokenResponse responseBody = new GetAccessTokenResponse();
-        com.aliyun.dingtalkoauth2_1_0.Client client = null;
-        try {
-            client = createClient();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest getAccessTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest()
-                .setAppKey(dingTalkConstant.DING_TALK_CLIENT_ID)
-                .setAppSecret(dingTalkConstant.DING_TALK_CLIENT_SECRET);
-        try {
-            responseBody = client.getAccessToken(getAccessTokenRequest);
-        } catch (TeaException err) {
-            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
-                // err 中含有 code 和 message 属性,可帮助开发定位问题
-            }
-        } catch (Exception _err) {
-            TeaException err = new TeaException(_err.getMessage(), _err);
-            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
-                // err 中含有 code 和 message 属性,可帮助开发定位问题
-            }
-        }
-        return responseBody.getBody().accessToken;
-    }
-
-    /**
-     * 获取钉钉userId
-     *
-     * @param userId 平台userid
-     * @return
-     */
-    public String getDingTalkUserId(Long userId) {
-        String dingTalkId = "";
-        LambdaQueryWrapper<MceMbuser> dingTalkQuery = Wrappers.lambdaQuery();
-        dingTalkQuery.select(MceMbuser::getDingTalkId, MceMbuser::getUserId)
-                .eq(MceMbuser::getUserId, userId);
-        MceMbuser mceMbuser = mceMbuserMapper.selectOne(dingTalkQuery);
-        if (mceMbuser != null) {
-            String dingId = mceMbuser.getDingTalkId();
-            if (dingId != null && dingId != "") {
-                return mceMbuser.getDingTalkId();
-            }
-        }
-        LambdaQueryWrapper<SysUser> phoneQuery = Wrappers.lambdaQuery();
-        phoneQuery.select(SysUser::getPhonenumber, SysUser::getUserName)
-                .eq(SysUser::getUserId, userId);
-        SysUser user = sysUserMapper.selectOne(phoneQuery);
-        String mobile = user.getPhonenumber();
-        try {
-            String accessToken = getDingTalkToken();
-            DingTalkClient client = new DefaultDingTalkClient(dingTalkConstant.DING_TALK_USERID_URL);
-            OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
-            req.setMobile(mobile);
-            OapiV2UserGetbymobileResponse rsp = client.execute(req, accessToken);
-            ObjectMapper objectMapper = new ObjectMapper();
-            JsonNode rootNode = objectMapper.readTree(rsp.getBody());
-            JsonNode resultNode = rootNode.get("result");
-            dingTalkId = resultNode.get("userid").asText();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        if (mceMbuser != null) {
-            mceMbuser.setDingTalkId(dingTalkId);
-            mceMbuser.setUpdateBy(SecurityUtils.getUsername());
-            mceMbuser.setUpdateTime(LocalDateTime.now());
-            mceMbuserMapper.update(mceMbuser, dingTalkQuery);
-        } else {
-            MceMbuser mbuser = new MceMbuser();
-            mbuser.setDingTalkId(dingTalkId);
-            mbuser.setPhone(mobile);
-            mbuser.setUserId(userId);
-            mbuser.setCreateBy(user.getUserName());
-            mbuser.setCreateTime(LocalDateTime.now());
-            mceMbuserMapper.insert(mbuser);
-        }
-        return dingTalkId;
-    }
-
-    @Async("asyncServiceExecutor")//异步发送
+    @Transactional
     @Override
-    public void sendDingTalkDailyReport(PmWorkReport workReport, List<PmWorkContent> workContents) {
-        String ccToStr = workReport.getCcTo();
-        String[] items = ccToStr.split(",");
-        List<Long> userIds = new ArrayList<>();
-        for (String item : items) {
-            long number = Long.parseLong(item.trim());
-            userIds.add(number);
-        }
-        List<String> ccTo = new ArrayList<>();
-        for (Long userId : userIds) {
-            String dingTalkUserId = getDingTalkUserId(userId);
-            ccTo.add(dingTalkUserId);
-        }
-        String reportCoordinateWork = workReport.getCoordinateWork();
-        String reportTomorrowPlan = workReport.getTomorrowPlan();
-        String coordinateWork1 = "-";
-        String tomorrowPlan1 = "-";
-        if (reportCoordinateWork != null && reportCoordinateWork != "") {
-            coordinateWork1 = reportCoordinateWork;
-        }
-        if (reportTomorrowPlan != null && reportTomorrowPlan != "") {
-            tomorrowPlan1 = reportTomorrowPlan;
-        }
+    public void timedSending(LocalDateTime time) {
+        log.info("定时报告任务开始---------------------------");
+        LambdaQueryWrapper<PmWorkReport> reports = Wrappers.lambdaQuery();
+        reports.eq(PmWorkReport::getReportStatus, 0)
+                .eq(PmWorkReport::getIsRegularlySend, 1)
+                .le(PmWorkReport::getTimingTime, time)
+                .orderByAsc(PmWorkReport::getTimingTime);
+        List<PmWorkReport> reportList = pmWorkReportMapper.selectList(reports);
+        if (!reportList.isEmpty()) {
+            List<Integer> reportIds = new ArrayList<>();
+            for (PmWorkReport report : reportList) {
+                reportIds.add(report.getId());
+            }
+            LambdaQueryWrapper<PmWorkContent> reportContents = Wrappers.lambdaQuery();
+            reportContents.in(PmWorkContent::getReportId, reportIds);
+            List<PmWorkContent> pmWorkContentList = pmWorkContentMapper.selectList(reportContents);
+            for (PmWorkReport report : reportList) {
+                Integer id = report.getId();
+                List<PmWorkContent> workContents = new ArrayList<>();
+                for (PmWorkContent content : pmWorkContentList) {
+                    Integer reportId = content.getReportId();
+                    if (reportId.equals(id)) {
+                        workContents.add(content);
+                    }
+                }
+                try {
+                    dingTalkAndMessage.sendAsyncMessage(report);
+                } catch (Exception e) {
+                    log.error("定时报告" + report.getId() + "调用消息中心异常" + e);
+                }
+                if (report.getSendDingTalk() == 1) {
+                    try {
+                        dingTalkAndMessage.sendDingTalkDailyReport(report, workContents);
+                    } catch (Exception e) {
+                        log.error("定时报告" + report.getId() + "发送钉钉异常" + e);
+                    }
+                }
 
-        StringBuilder contentBuilder = new StringBuilder();
-        for (PmWorkContent content : workContents) {
-            String projectName = content.getProjectName();
-            BigDecimal workTime = content.getWorkTime();
-            String workContent = content.getWorkContent();
-            StringBuilder markdown = new StringBuilder();
-            markdown.append("#### ").append(projectName).append(" ").append(workTime).append("h\n\n");
-            markdown.append("<span style=\"font-size: 18px;\">").append(workContent).append("\n").append("</span>");
-            contentBuilder.append(markdown);
-        }
-        String completedWork = contentBuilder.toString();
-        try {
-            DingTalkClient client = new DefaultDingTalkClient(dingTalkConstant.DING_TALK_CREATE_DAILY_REPORT_URL);
-            OapiReportCreateRequest req = new OapiReportCreateRequest();
-            OapiReportCreateRequest.OapiCreateReportParam obj1 = new OapiReportCreateRequest.OapiCreateReportParam();
-            List<OapiReportCreateRequest.OapiReportContentVo> list3 = new ArrayList<>();
-            OapiReportCreateRequest.OapiReportContentVo completedWorkD = new OapiReportCreateRequest.OapiReportContentVo();
-            completedWorkD.setSort(0L);
-            completedWorkD.setType(1L);
-            completedWorkD.setContentType(dingTalkConstant.DING_TALK_DAILY_REPORT_CONTENT_TYPE);
-            completedWorkD.setContent(completedWork);
-            completedWorkD.setKey(dingTalkConstant.DING_TALK_DAILY_REPORT_COMPLETED_WORK);
-            list3.add(completedWorkD);
-            OapiReportCreateRequest.OapiReportContentVo tomorrowPlan = new OapiReportCreateRequest.OapiReportContentVo();
-            tomorrowPlan.setSort(1L);
-            tomorrowPlan.setType(1L);
-            tomorrowPlan.setContentType(dingTalkConstant.DING_TALK_DAILY_REPORT_CONTENT_TYPE);
-            tomorrowPlan.setContent(tomorrowPlan1);
-            tomorrowPlan.setKey(dingTalkConstant.DING_TALK_DAILY_REPORT_TOMORROW_PLAN);
-            list3.add(tomorrowPlan);
-            OapiReportCreateRequest.OapiReportContentVo coordinateWork = new OapiReportCreateRequest.OapiReportContentVo();
-            coordinateWork.setSort(2L);
-            coordinateWork.setType(1L);
-            coordinateWork.setContentType(dingTalkConstant.DING_TALK_DAILY_REPORT_CONTENT_TYPE);
-            coordinateWork.setContent(coordinateWork1);
-            coordinateWork.setKey(dingTalkConstant.DING_TALK_DAILY_REPORT_COORDINATE_WORK);
-            list3.add(coordinateWork);
-            obj1.setContents(list3);
-            obj1.setToUserids(ccTo);
-            obj1.setTemplateId(dingTalkConstant.DING_TALK_DAILY_REPORT_TEMPLATE_ID);
-            obj1.setToChat(dingTalkConstant.DING_TALK_DAILY_REPORT_TO_CHAT);
-            obj1.setDdFrom(dingTalkConstant.DING_TALK_CORP_ID);
-            obj1.setUserid(getDingTalkUserId(SecurityUtils.getUserId()));
-            //obj1.setToCids(dingTalkConstant.DING_TALK_DAILY_REPORT_TO_CIDS);//发送到群,群id
-            req.setCreateReportParam(obj1);
-            OapiReportCreateResponse rsp = client.execute(req, getDingTalkToken());
-            if (rsp.isSuccess()) {
-                log.info("钉钉报告发送成功");
-            } else {
-                log.error("钉钉报告发送失败: " + rsp.getErrmsg());
+                report.setReportStatus(1);
+                pmWorkReportMapper.updateById(report);
             }
-        } catch (Exception e) {
-            e.printStackTrace();
         }
+        log.info("定时报告任务结束---------------------------");
     }
 
 

+ 3 - 0
service-iot/service-iot-biz/src/main/resources/mapper/iot/PmWorkReportMapper.xml

@@ -19,6 +19,9 @@
         <result column="dept_id" property="deptId" />
         <result column="tenant_id" property="tenantId" />
         <result column="send_ding_talk" property="sendDingTalk" />
+        <result column="timing_time" property="timingTime" />
+        <result column="report_status" property="reportStatus" />
+        <result column="is_regularly_send" property="isRegularlySend" />
     </resultMap>
 
 </mapper>