Lijy 4 天之前
父節點
當前提交
2a37344fa2
共有 16 個文件被更改,包括 613 次插入29 次删除
  1. 18 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ContractPayCustomizedController.java
  2. 19 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  3. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Contract.java
  4. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractCustom.java
  5. 11 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractPayCustomized.java
  6. 11 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectMain.java
  7. 17 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/WorkOrderNumVo.java
  8. 3 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  9. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExcelExportService.java
  10. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  11. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java
  12. 126 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java
  13. 160 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  14. 184 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/ExcelUtil.java
  15. 18 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  16. 12 23
      fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

+ 18 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ContractPayCustomizedController.java

@@ -1,10 +1,18 @@
 package com.management.platform.controller;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.ContractPayCustomized;
+import com.management.platform.service.ContractPayCustomizedService;
+import com.management.platform.util.HttpRespMsg;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
 /**
  * <p>
  *  前端控制器
@@ -16,6 +24,16 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 @RequestMapping("/contract-pay-customized")
 public class ContractPayCustomizedController {
+    @Resource
+    private ContractPayCustomizedService contractPayCustomizedService;
+
+    @RequestMapping("/getStampDutyTimeNullList")
+    public HttpRespMsg getStampDutyTimeNullList(Integer contractId,HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        List<ContractPayCustomized> list = contractPayCustomizedService.list(new QueryWrapper<ContractPayCustomized>().eq("contract_id", contractId).isNotNull("stamp_duty_time"));
+        httpRespMsg.setData(list);
+        return httpRespMsg;
+    }
 
 }
 

+ 19 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -1550,5 +1550,24 @@ public class ProjectController {
     public HttpRespMsg initTaskGroupsFromTemplate(Integer companyId){
         return projectService.initTaskGroups(companyId);
     }
+
+    /**
+     * 统计角色为“质量适航团队”、“工程技术”人员在一定时间段内(时间段可选),有工作包令号的主项目上的工时个人总和
+     * @param pageIndex
+     * @param pageSize
+     * @param startDate
+     * @param endDate
+     * @param request
+     * @return
+     */
+    @RequestMapping("/getWorkOrderNumStatistics")
+    public HttpRespMsg getWorkOrderNumStatistics(Integer pageIndex, Integer pageSize,String startDate,String endDate,HttpServletRequest request){
+        return projectService.getWorkOrderNumStatistics(pageIndex,pageSize,startDate,endDate,request);
+    }
+
+    @RequestMapping("/exportWorkOrderNumStatistics")
+    public HttpRespMsg exportWorkOrderNumStatistics(String startDate,String endDate,HttpServletRequest request) throws Exception {
+        return projectService.exportWorkOrderNumStatistics(startDate,endDate,request);
+    }
 }
 

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Contract.java

@@ -125,6 +125,12 @@ public class Contract extends Model<Contract> {
     @TableField("status")
     private Integer status;
 
+    /**
+     * 采购方式:0公开招标、1邀请招标、2询比价、3竞争性谈判、4单一来源
+     */
+    @TableField("procurement_way")
+    private Integer procurementWay;
+
 
     /**
      * 创建时间

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractCustom.java

@@ -5,9 +5,12 @@ import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -120,6 +123,23 @@ public class ContractCustom extends Model<ContractCustom> {
     @TableField("stamp_duty_items")
     private String stampDutyItems;
 
+    /**
+     * 印花税缴纳状态 0无需缴纳、1未缴纳、2已缴纳、3部分缴纳。
+     * 合同新增后,默认置值未缴纳,状态随时可修改,不予审核状态关联
+     */
+    @TableField("stamp_duty_status")
+    private Integer stampDutyStatus;
+
+    /**
+     * 印花税缴纳时间(最新)
+     * 印花税缴纳状态为无需缴纳、未缴纳时,禁用;
+     * 部分缴纳、已缴纳时,启用。
+     */
+    @TableField("stamp_duty_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Integer stampDutyTime;
+
 
     @Override
     protected Serializable pkVal() {

+ 11 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ContractPayCustomized.java

@@ -5,9 +5,12 @@ import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -90,6 +93,14 @@ public class ContractPayCustomized extends Model<ContractPayCustomized> {
     @TableField("pay_type")
     private Boolean payType;
 
+    /**
+     * 印花税缴纳时间
+     */
+    @TableField("stamp_duty_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private String stampDutyTime;
+
 
     @Override
     protected Serializable pkVal() {

+ 11 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectMain.java

@@ -43,6 +43,17 @@ public class ProjectMain extends Model<ProjectMain> {
     @TableField("company_id")
     private Integer companyId;
 
+    /**
+     * 工作包令号
+     */
+    @TableField("work_order_num")
+    private String workOrderNum;
+
+    /**
+     * 包令号类型 0主飞控,1自动飞行,2高升力
+     */
+    @TableField("work_order_num_type")
+    private Integer workOrderNumType;
 
     @Override
     protected Serializable pkVal() {

+ 17 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/WorkOrderNumVo.java

@@ -0,0 +1,17 @@
+package com.management.platform.entity.vo;
+
+import lombok.Data;
+
+
+@Data
+public class WorkOrderNumVo {
+    private String userId;
+    private String roleName;
+    private String corpwxUserid;
+    private String dingdingUserid;
+    private String userName;
+    private Double sumWorkTime;
+    private String workOrderNum;
+    private Integer workOrderNumType;
+    private String mainName;
+}

+ 3 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java

@@ -2,10 +2,7 @@ package com.management.platform.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.management.platform.entity.Project;
-import com.management.platform.entity.vo.CustomerProject;
-import com.management.platform.entity.vo.ProjectWithStage;
-import com.management.platform.entity.vo.StageCost;
-import com.management.platform.entity.vo.UserCateTimeVo;
+import com.management.platform.entity.vo.*;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Update;
 
@@ -277,4 +274,6 @@ public interface ProjectMapper extends BaseMapper<Project> {
     void batchInsert(@Param("toAddList") List<Project> toAddList);
 
     List<Map<String, Object>> getTimeCostByWorkNum(Integer companyId, String startDate, String endDate,List<Integer> deptIds);
+
+    List<WorkOrderNumVo> getWorkOrderNumStatistics(Integer pageIndex, Integer pageSize, String startDate, String endDate);
 }

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExcelExportService.java

@@ -4,6 +4,7 @@ import com.management.platform.entity.CompanyDingding;
 import com.management.platform.entity.WxCorpInfo;
 import com.management.platform.util.HttpRespMsg;
 
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -21,4 +22,5 @@ public interface ExcelExportService {
     HttpRespMsg exportMultiSheetGeneralExcelTotal(WxCorpInfo wxCorpInfo, CompanyDingding dingding, String title, List<List<String>>[] multiSheetList, String downloadPath, String[] sheetsName) throws Exception;
 
     HttpRespMsg exportGeneralExcelTotal(WxCorpInfo wxCorpInfo, CompanyDingding dingding, String fileName, List<List<String>> allList, String path) throws Exception ;
+    HttpRespMsg exportShanghaiHangKongList(WxCorpInfo wxCorpInfo, CompanyDingding dingding, String fileName, LinkedHashMap<String, Object> totalMap, String path) throws Exception;
 }

+ 4 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java

@@ -336,4 +336,8 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg getTimeCostByWorkNum(String startDate, String endDate,Integer deptId, HttpServletRequest request);
 
     HttpRespMsg exportTimeCostByWorkNum(String startDate, String endDate,Integer deptId, HttpServletRequest request);
+
+    HttpRespMsg getWorkOrderNumStatistics(Integer pageIndex, Integer pageSize, String startDate, String endDate, HttpServletRequest request);
+
+    HttpRespMsg exportWorkOrderNumStatistics(String startDate, String endDate, HttpServletRequest request) throws Exception;
 }

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java

@@ -1226,8 +1226,8 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
             headList.add("合同号");
             headList.add("合同类别");
             headList.add("二级分类");
-            headList.add("对方单位");
-            headList.add("对方联系人");
+            headList.add("供应商名称");
+            headList.add("供应商联系人");
             headList.add("对方联系电话");
             headList.add("使用部门");
             headList.add("经费来源");

+ 126 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest;
 import java.io.File;
 import java.time.LocalDateTime;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -321,6 +322,131 @@ public class ExcelExportServiceImpl implements ExcelExportService {
         return httpRespMsg;
     }
 
+    @Override
+    public HttpRespMsg exportShanghaiHangKongList(WxCorpInfo wxCorpInfo, CompanyDingding dingding, String title, LinkedHashMap<String, Object> totalMap, String downloadPath) throws Exception {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        if (title.contains("/")) {
+            //文件名不能含有路径,得替换掉
+            title = title.replace("/", "@");
+        }
+        if (title.contains("\\")) {
+            //文件名不能含有路径,得替换掉
+            title = title.replace("\\", "@");
+        }
+        String resp = ExcelUtil.exportShanghaiHangKongList(totalMap, downloadPath);
+        String fileUrlSuffix = title + ".xlsx";
+        if(wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1){
+            FileSystemResource fileSystemResource = new FileSystemResource(path+fileUrlSuffix);
+//            String md5 = DigestUtils.md5Hex(FileUtil.readBytes(fileSystemResource.getFile()));
+
+            Long checkSize = 20L*1024*1024;
+            if(fileSystemResource.getFile().length() >= checkSize){
+                httpRespMsg.setError("文件过大,请缩短查询日期范围");
+                return httpRespMsg;
+            }
+            String jobId = "";
+            String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+            jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+//            if(fileSystemResource.getFile().length() >= checkSize){
+//                String tmpFileJobId = wxCorpInfoService.getTranslationJobId(fileUrlSuffix,md5,wxCorpInfo);
+//                if(!StringUtils.isEmpty(tmpFileJobId)){
+//                    String mediaId = wxCorpInfoService.getAsyncJobResult(tmpFileJobId,wxCorpInfo);
+//                    jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+//                }
+//            }else{
+//                String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+//                jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+//            }
+
+            System.out.println("上传待转译文件到企业微信, jobId==" + jobId);
+//            if(StringUtils.isEmpty(jobId)){
+//                httpRespMsg.setError("转义jobId为空,请联系管理员");
+//                return httpRespMsg;
+//            }
+            int i = 0;
+            String syncTranslationResult = null;
+            /**
+             * 异步上传转译文件的任务完成时会触发回调,在WeiXinCorpController中的commonDevCallbackPost实现了对回调的处理,存储到corpwxJobResult表中
+             * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+             */
+            long t = System.currentTimeMillis();
+            while (i < 40) {
+                if (i < 10) {
+                    Thread.sleep(300);
+                } else if (i < 20){
+                    Thread.sleep(1000);
+                } else {
+                    Thread.sleep(3000);
+                }
+                System.out.println("i=="+i+", "+LocalDateTime.now());
+                CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
+                if (corpwxJobResult != null) {
+                    if (corpwxJobResult.getErrCode() == 0) {
+                        syncTranslationResult = wxCorpInfoService.getSyncTranslationResult(jobId);
+                        corpwxJobCenter.remove(jobId);
+                    } else {
+                        long t2 = System.currentTimeMillis();
+                        System.out.println("222企业微信转译报错:"+corpwxJobResult.getErrMsg()+",耗时:" + (t2 - t) + "ms");
+                        httpRespMsg.setError(corpwxJobResult.getErrMsg());
+                        return httpRespMsg;
+                    }
+                    break;
+                }
+                i++;
+            }
+            if (syncTranslationResult != null) {
+                long t2 = System.currentTimeMillis();
+                System.out.println("企业微信转译文件后地址是:"+syncTranslationResult+",耗时:" + (t2 - t) + "ms");
+                httpRespMsg.data = syncTranslationResult;
+            } else {
+                //httpRespMsg.setError("处理超时...");
+                httpRespMsg.setError(MessageUtils.message("request.outTime"));
+            }
+        }else if(dingding != null && dingding.getContactNeedTranslate() == 1){
+            User user = userMapper.selectById(request.getHeader("token"));
+            String mediaId = dingDingService.getTranslationMediaId(fileUrlSuffix,dingding);
+            String jobId = dingDingService.syncTranslation(mediaId,fileUrlSuffix, user.getDingdingUnionid(),dingding);
+            System.out.println("上传待转译文件到钉钉, jobId==" + jobId);
+            int i = 0;
+            String syncTranslationResult = null;
+            /**
+             * 异步上传转译文件的任务完成时会触发回调,在DingDingController中的callback实现了对回调的处理,存储到corpddJobCenter缓存中
+             * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+             */
+            long t = System.currentTimeMillis();
+            while (i < 30) {
+                if (i < 10) {
+                    Thread.sleep(300);
+                } else if (i < 20){
+                    Thread.sleep(1000);
+                } else {
+                    Thread.sleep(3000);
+                }
+                System.out.println("i=="+i+", "+LocalDateTime.now());
+                Integer status = corpddJobCenter.get(jobId);
+                if (status != null) {
+                    if (status == 1) {
+                        syncTranslationResult = dingDingService.getSyncTranslationResult(jobId,dingding);
+                        corpddJobCenter.remove(jobId);
+                    }
+                    break;
+                }
+                i++;
+            }
+            if (syncTranslationResult != null) {
+                long t2 = System.currentTimeMillis();
+                System.out.println("钉钉转译文件后地址是:"+syncTranslationResult+",耗时:" + (t2 - t) + "ms");
+                httpRespMsg.data = syncTranslationResult;
+            } else {
+                //httpRespMsg.setError("处理超时...");
+                httpRespMsg.setError(MessageUtils.message("request.outTime"));
+            }
+        }else {
+            httpRespMsg.data = resp;
+        }
+        return httpRespMsg;
+    }
+
     @Override
     public HttpRespMsg exportGeneralExcelByTitleAndListByZheZhong(WxCorpInfo wxCorpInfo, CompanyDingding dingding, String title, List<List<String>> list, String downloadPath) throws Exception {
         HttpRespMsg httpRespMsg = new HttpRespMsg();

+ 160 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -14140,6 +14140,166 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return httpRespMsg;
     }
 
+    @Override
+    public HttpRespMsg getWorkOrderNumStatistics(Integer pageIndex, Integer pageSize, String startDate, String endDate, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+        CompanyDingding dingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", user.getCompanyId()));
+        List<ProjectMain> projectMainList= projectMainMapper.selectList(new QueryWrapper<ProjectMain>().eq("company_id",4215).isNotNull("work_order_num_type").orderByAsc("work_order_num_type"));
+        //包令号类型 0主飞控,1自动飞行,2高升力
+        List<ProjectMain> typeCollect0 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 0).collect(Collectors.toList());
+        List<ProjectMain> typeCollect1 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 1).collect(Collectors.toList());
+        List<ProjectMain> typeCollect2 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 2).collect(Collectors.toList());
+        List<String> typeNum0= typeCollect0.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
+        List<String> typeNum1= typeCollect1.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
+        List<String> typeNum2= typeCollect2.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
+        LinkedHashMap<String, Object> totalMap = new LinkedHashMap<>();
+        totalMap.put("totalRow",projectMainList.size());//总列数
+        totalMap.put("mainFly",typeCollect0.size());
+        totalMap.put("mainFlyNumStrs",typeNum0);//主飞控包令号列表
+        totalMap.put("auto",typeCollect1.size());
+        totalMap.put("autoNumStrs",typeNum1);//自动
+        totalMap.put("high",typeCollect2.size());
+        totalMap.put("highNumStrs",typeNum2);//高升力包令号列表
+
+        List<WorkOrderNumVo> list= projectMapper.getWorkOrderNumStatistics(null,null,startDate,endDate);
+        Map<String, List<WorkOrderNumVo>> userCollect = list.stream().collect(Collectors.groupingBy(WorkOrderNumVo::getUserId));
+        Set<Map.Entry<String, List<WorkOrderNumVo>>> entries = userCollect.entrySet();
+
+        ArrayList<ArrayList<String>> dataList = new ArrayList<>();
+        for (Map.Entry<String, List<WorkOrderNumVo>> entry : entries) {
+            List<WorkOrderNumVo> voList = entry.getValue();
+            double total = voList.stream()
+                    .mapToDouble(v -> v.getSumWorkTime())  // 转为 DoubleStream
+                    .reduce(0.0, Double::sum);
+            ArrayList<String> numString = new ArrayList<>();
+            numString.add(voList.get(0).getRoleName());
+            numString.add(voList.get(0).getUserName());
+            for (String s : typeNum0) {
+                Optional<WorkOrderNumVo> first = voList.stream().filter(v -> v.getWorkOrderNum().equals(s)).findFirst();
+                if (first.isPresent()){
+                    numString.add(first.get().getSumWorkTime().toString());
+                }else {
+                    numString.add("");
+                }
+            }
+            for (String s : typeNum1) {
+                Optional<WorkOrderNumVo> first = voList.stream().filter(v -> v.getWorkOrderNum().equals(s)).findFirst();
+                if (first.isPresent()){
+                    numString.add(first.get().getSumWorkTime().toString());
+                }else {
+                    numString.add("");
+                }
+            }
+            for (String s : typeNum2) {
+                Optional<WorkOrderNumVo> first = voList.stream().filter(v -> v.getWorkOrderNum().equals(s)).findFirst();
+                if (first.isPresent()){
+                    numString.add(first.get().getSumWorkTime().toString());
+                }else {
+                    numString.add("");
+                }
+            }
+            numString.add(total+"");//合计
+            dataList.add(numString);
+        }
+
+        // 内存分页处理
+        int totalCount = dataList.size();
+        if (pageIndex != null && pageSize != null) {
+            // 确保 pageIndex ≥ 1
+            int safePageIndex = Math.max(1, pageIndex);
+            int fromIndex = (safePageIndex - 1) * pageSize;
+            int toIndex = Math.min(fromIndex + pageSize, totalCount);
+
+            if (fromIndex < totalCount) {
+                dataList = new ArrayList<>(dataList.subList(fromIndex, toIndex));
+            } else {
+                dataList = new ArrayList<>(); // 超出范围,返回空列表
+            }
+        }
+        totalMap.put("dataList",dataList);
+        totalMap.put("totalCount", totalCount);
+        httpRespMsg.setData(totalMap);
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg exportWorkOrderNumStatistics(String startDate, String endDate, HttpServletRequest request) throws Exception {
+        User user = userMapper.selectById(request.getHeader("token"));
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+        CompanyDingding dingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", user.getCompanyId()));
+        List<ProjectMain> projectMainList= projectMainMapper.selectList(new QueryWrapper<ProjectMain>().eq("company_id",4215).isNotNull("work_order_num_type").orderByAsc("work_order_num_type"));
+        List<WorkOrderNumVo> list= projectMapper.getWorkOrderNumStatistics(null,null,startDate,endDate);
+        Map<String, List<WorkOrderNumVo>> userCollect = list.stream().collect(Collectors.groupingBy(WorkOrderNumVo::getUserId));
+        Set<Map.Entry<String, List<WorkOrderNumVo>>> entries = userCollect.entrySet();
+
+        //包令号类型 0主飞控,1自动飞行,2高升力
+        List<ProjectMain> typeCollect0 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 0).collect(Collectors.toList());
+        List<ProjectMain> typeCollect1 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 1).collect(Collectors.toList());
+        List<ProjectMain> typeCollect2 = projectMainList.stream().filter(m -> m.getWorkOrderNumType() == 2).collect(Collectors.toList());
+        List<String> typeNum0= typeCollect0.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
+        List<String> typeNum1= typeCollect1.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
+        List<String> typeNum2= typeCollect2.stream().map(ProjectMain::getWorkOrderNum).collect(Collectors.toList());
+
+        LinkedHashMap<String, Object> totalMap = new LinkedHashMap<>();
+        totalMap.put("totalRow",projectMainList.size());//总列数
+        totalMap.put("mainFly",typeCollect0.size());
+        totalMap.put("mainFlyNumStrs",typeNum0);//主飞控包令号列表
+        totalMap.put("auto",typeCollect1.size());
+        totalMap.put("autoNumStrs",typeNum1);//自动
+        totalMap.put("high",typeCollect2.size());
+        totalMap.put("highNumStrs",typeNum2);//高升力包令号列表
+
+        ArrayList<ArrayList<String>> dataList = new ArrayList<>();
+        for (Map.Entry<String, List<WorkOrderNumVo>> entry : entries) {
+            List<WorkOrderNumVo> voList = entry.getValue();
+            double total = voList.stream()
+                    .mapToDouble(v -> v.getSumWorkTime())  // 转为 DoubleStream
+                    .reduce(0.0, Double::sum);
+            ArrayList<String> numString = new ArrayList<>();
+            numString.add(voList.get(0).getRoleName());
+
+            //转义
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                numString.add("$userName="+(voList.get(0).getCorpwxUserid()==null?" ":voList.get(0).getCorpwxUserid())+"$");
+            }else if(dingding!=null&&dingding.getContactNeedTranslate()==1){
+                numString.add("$userName="+(voList.get(0).getDingdingUserid()==null?" ":voList.get(0).getDingdingUserid())+"$");
+            }else {
+                numString.add(voList.get(0).getUserName());
+            }
+
+            for (String s : typeNum0) {
+                Optional<WorkOrderNumVo> first = voList.stream().filter(v -> v.getWorkOrderNum().equals(s)).findFirst();
+                if (first.isPresent()){
+                    numString.add(first.get().getSumWorkTime().toString());
+                }else {
+                    numString.add("");
+                }
+            }
+            for (String s : typeNum1) {
+                Optional<WorkOrderNumVo> first = voList.stream().filter(v -> v.getWorkOrderNum().equals(s)).findFirst();
+                if (first.isPresent()){
+                    numString.add(first.get().getSumWorkTime().toString());
+                }else {
+                    numString.add("");
+                }
+            }
+            for (String s : typeNum2) {
+                Optional<WorkOrderNumVo> first = voList.stream().filter(v -> v.getWorkOrderNum().equals(s)).findFirst();
+                if (first.isPresent()){
+                    numString.add(first.get().getSumWorkTime().toString());
+                }else {
+                    numString.add("");
+                }
+            }
+            numString.add(total+"");//合计
+            dataList.add(numString);
+        }
+        totalMap.put("dataList", dataList);
+        return excelExportService.exportShanghaiHangKongList(wxCorpInfo,dingding,"工作包令号_主项目个人工时统计表",totalMap,path);
+    }
+
     //导出FTE报表数据
     @Override
     public HttpRespMsg exportFTEData(String monthStart,String monthEnd, String area,Integer departmentId,HttpServletRequest request) {

+ 184 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/ExcelUtil.java

@@ -19,9 +19,12 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.poi.ss.usermodel.TableStyleType.headerRow;
+
 @Component
 public class ExcelUtil {
     /**
@@ -1779,4 +1782,185 @@ public class ExcelUtil {
         }
         return "/upload/"+fileName;
     }
+
+    public static String exportShanghaiHangKongList(LinkedHashMap<String, Object> totalMap, String path) {
+        String result="系统提示:Excel文件导出成功!";
+        String fileName= "工作包令号_主项目个人工时统计表"+System.currentTimeMillis()+".xlsx";
+
+        try {
+            // 创建工作簿
+            SXSSFWorkbook workBook = new SXSSFWorkbook();
+            // 创建工作类
+
+            Sheet sheetOne = workBook.createSheet();
+            workBook.setSheetName(0,"主项目个人工时统计表");
+            sheetOne.setDefaultColumnWidth(16);
+
+            //设置字体样式
+            Font headFont = workBook.createFont();
+            headFont.setBold(true);
+            headFont.setFontHeightInPoints((short) 10);
+            headFont.setFontName("黑体");
+
+            Font titleFont = workBook.createFont();
+            titleFont.setBold(true);
+            titleFont.setFontHeightInPoints((short) 10);
+            titleFont.setFontName("黑体");
+
+            Font font = workBook.createFont();
+            font.setFontHeightInPoints((short) 10);
+            font.setFontName("宋体");
+
+            //设置单元格样式
+            XSSFCellStyle  headStyle = (XSSFCellStyle) workBook.createCellStyle();
+            headStyle.setFont(headFont);
+            headStyle.setAlignment(HorizontalAlignment.CENTER);
+            headStyle.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER);
+            headStyle.setWrapText(true);
+            headStyle.setBorderBottom(BorderStyle.THIN); //下边框
+            headStyle.setBorderLeft(BorderStyle.THIN);//左边框
+            headStyle.setBorderTop(BorderStyle.THIN);//上边框
+            headStyle.setBorderRight(BorderStyle.THIN);//右边框
+
+
+
+            //设置自定义颜色
+            XSSFColor xssfColor = new XSSFColor();
+            byte[] colorRgb = { (byte)118, (byte)147, (byte)60 };
+            xssfColor.setRGB(colorRgb);
+
+
+            CellStyle titleStyle = workBook.createCellStyle();
+            titleStyle.setFont(titleFont);
+            titleStyle.setAlignment(HorizontalAlignment.CENTER);
+            titleStyle.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER);
+            titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);  //填充单元格
+            titleStyle.setFillForegroundColor((short)9);    //填色
+            titleStyle.setWrapText(true);
+            titleStyle.setBorderBottom(BorderStyle.THIN); //下边框
+            titleStyle.setBorderLeft(BorderStyle.THIN);//左边框
+            titleStyle.setBorderTop(BorderStyle.THIN);//上边框
+            titleStyle.setBorderRight(BorderStyle.THIN);//右边框
+
+            CellStyle cellStyle = workBook.createCellStyle();
+            cellStyle.setFont(font);
+            cellStyle.setAlignment(HorizontalAlignment.CENTER);
+            cellStyle.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER);
+            cellStyle.setWrapText(true);
+            cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
+            cellStyle.setBorderLeft(BorderStyle.THIN);//左边框
+            cellStyle.setBorderTop(BorderStyle.THIN);//上边框
+            cellStyle.setBorderRight(BorderStyle.THIN);//右边框
+
+            // 设置边框颜色(重要!)
+            cellStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
+            cellStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
+            cellStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
+            cellStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
+
+            // 创建表头行第一行
+            Row headerRowFirst = sheetOne.createRow(0);
+            Integer totalRow = (Integer) totalMap.get("totalRow");
+            for (int i = 0; i < totalRow + 3; i++) {
+                Cell cell = headerRowFirst.createCell(i);
+                cell.setCellStyle(headStyle);
+                if (i==0){
+                    cell.setCellValue("统计时间");
+                }else{
+                    cell.setCellValue("");
+                }
+            }
+            sheetOne.addMergedRegion(new CellRangeAddress(0, 0, 0, totalRow+2));//合并第一行
+            // 创建表头行第二行
+            Row headerRowSecond = sheetOne.createRow(1);
+            for (int i = 0; i < totalRow + 3; i++) {
+                Cell cell = headerRowSecond.createCell(i);
+                cell.setCellStyle(headStyle);
+                if (i<=1){
+                    cell.setCellValue("成员信息");
+                }else if (i<totalRow + 2){
+                    cell.setCellValue("工作包令号");
+                }else {
+                    cell.setCellValue("合计");
+                }
+            }
+            sheetOne.addMergedRegion(new CellRangeAddress(1, 1, 2, totalRow+1));//合并第二行
+
+            // 创建表头行第三行
+            Row headerRowThird = sheetOne.createRow(2);
+            Integer mainFly = (Integer) totalMap.get("mainFly");
+            Integer auto = (Integer) totalMap.get("auto");
+            Integer high = (Integer) totalMap.get("high");
+
+            for (int i = 0; i < totalRow + 3; i++) {
+                Cell cell = headerRowThird.createCell(i);
+                cell.setCellStyle(headStyle);
+                if (i<=1){
+                    cell.setCellValue("成员信息");
+                }else if (i<(mainFly+2)){
+                    cell.setCellValue("主飞控");
+                }else if (i<(mainFly+auto+2)){
+                    cell.setCellValue("自动飞行");
+                }else if (i<(mainFly+auto+high+2)){
+                    cell.setCellValue("高升力");
+                }else {
+                    cell.setCellValue("合计");
+                }
+            }
+            sheetOne.addMergedRegion(new CellRangeAddress(2, 2, 2, mainFly+1));//合并第三行
+            sheetOne.addMergedRegion(new CellRangeAddress(2, 2, 2+mainFly, mainFly+auto+1));//合并第三行
+            sheetOne.addMergedRegion(new CellRangeAddress(2, 2, 2+mainFly+auto, mainFly+auto+high+1));//合并第三行
+
+            sheetOne.addMergedRegion(new CellRangeAddress(1, 2, 0, 1));//成员信息合并
+
+
+            // 创建表头行第四行
+            Row headerRowFourth = sheetOne.createRow(3);
+            List<String> mainFlyNumStrs = (ArrayList<String>) totalMap.get("mainFlyNumStrs");
+            List<String> autoNumStrs = (ArrayList<String>) totalMap.get("autoNumStrs");
+            List<String> highNumStrs = (ArrayList<String>) totalMap.get("highNumStrs");
+            ArrayList<String> titleStrs = new ArrayList<>();
+            titleStrs.add("角色");
+            titleStrs.add("姓名");
+            titleStrs.addAll(mainFlyNumStrs);
+            titleStrs.addAll(autoNumStrs);
+            titleStrs.addAll(highNumStrs);
+            titleStrs.add("合计");
+
+
+            for (int i = 0; i < titleStrs.size(); i++) {
+                Cell cell = headerRowFourth.createCell(i);
+                cell.setCellStyle(headStyle);
+                cell.setCellValue(titleStrs.get(i));
+            }
+            sheetOne.addMergedRegion(new CellRangeAddress(1, 3, totalRow+2, totalRow+2));//合计合并
+
+
+            ArrayList<ArrayList<String>> dataList = (ArrayList<ArrayList<String>>) totalMap.get("dataList");
+            if (!dataList.isEmpty()){
+                for (int i = 0; i < dataList.size(); i++) {
+                    Row row = sheetOne.createRow(4+i);
+                    ArrayList<String> strings = dataList.get(i);
+                    for (int j = 0; j < strings.size(); j++) {
+                        Cell cell = row.createCell(j);
+                        cell.setCellStyle(cellStyle);
+                        cell.setCellValue(strings.get(j));
+                    }
+                }
+            }
+
+            File dir = new File(path);
+            if (!dir.exists()) {
+                dir.mkdirs();
+            }
+            FileOutputStream os = new FileOutputStream(path+fileName);//保存到本地
+            workBook.write(os);
+            os.flush();
+            os.close();
+        }catch(Exception e) {
+            System.out.println(result);
+            e.printStackTrace();
+        }
+        return "/upload/"+fileName;
+    }
 }

+ 18 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml

@@ -3026,6 +3026,24 @@
             END
         ORDER BY workNum ASC
     </select>
+    <select id="getWorkOrderNumStatistics" resultType="com.management.platform.entity.vo.WorkOrderNumVo">
+        select u.id userId, u.role_name as roleName,u.corpwx_userid corpwxUserid,u.dingding_userid dingdingUserid,u.name as userName,sum(r.working_time) sumWorkTime,
+               pm.work_order_num workOrderNum,pm.work_order_num_type workOrderNumType,pm.name mainName
+        from report r
+                 LEFT JOIN user u on r.creator_id =u.id
+                 LEFT JOIN project p on r.project_id=p.id
+                 LEFT JOIN project_main pm on p.project_main_id=pm.id
+        where u.role_id in (25750,53996)
+          and u.company_id=4215 and u.is_active=1
+          and pm.work_order_num_type is not null
+        <if test="startDate!=null and startDate !='' and endDate!=null and endDate !='' ">
+            and r.create_date BETWEEN #{startDate} and #{endDate}
+        </if>
+        GROUP BY u.id ,pm.id
+        <if test="pageIndex!=null and pageSize !=null">
+            LIMIT #{pageIndex} ,#{pageSize}
+        </if>
+    </select>
 
 
 </mapper>

+ 12 - 23
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -433,6 +433,8 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
             reqParam.put("agentid", corpInfo.getAgentid());
             JSONObject cardJson = new JSONObject();
             String title = "";
+            String urlStr = "";
+            String encodedRedirectUri = "";
             String jumpUrl ;
             if(isPrivateDeploy){
                 jumpUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+corpInfo.getCorpid()+"&redirect_uri="+ authUrl +"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
@@ -452,9 +454,8 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                         dates+=plan.getEndDate().format(DateTimeFormatter.BASIC_ISO_DATE);
                     }
                     //http://mobworkshop.njlew.com.cn:16080
-                    StringBuilder builder = new StringBuilder(mobUrl);
-                    builder.append("/#/distribution")
-                            .append("?id=").append(plan.getId())
+                    StringBuilder builder = new StringBuilder("/#/distribution");
+                    builder.append("?id=").append(plan.getId())
                             .append("&departmentId=").append(plan.getStationId())
                             .append("&titleText=")
                             .append(URLEncoder.encode("今日计划", "UTF-8"))
@@ -466,11 +467,11 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                     if (StringUtils.isNotEmpty(plan.getProductName())){
                         builder.append("&productName=").append(URLEncoder.encode(plan.getProductName(), "UTF-8"));
                     }
-                    String urlStr =builder.toString();
-                    String encodedRedirectUri = URLEncoder.encode(urlStr, "UTF-8");
+                    urlStr =builder.toString();
+                    encodedRedirectUri = URLEncoder.encode(urlStr, "UTF-8");
                     log.info("urlStr==>"+urlStr);
                     log.info("encodedRedirectUri==>"+encodedRedirectUri);
-                    jumpUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+corpInfo.getCorpid()+"&redirect_uri="+ encodedRedirectUri +"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
+                    jumpUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+corpInfo.getCorpid()+"&redirect_uri="+ authUrl +"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
                     log.info("jumpUrl==>"+jumpUrl);
                 }
             }
@@ -500,28 +501,16 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                     if (StringUtils.isNotEmpty(plan.getProductName())){
                         builder.append("&productName=").append(URLEncoder.encode(plan.getProductName(), "UTF-8"));
                     }
-                    String urlStr =builder.toString();
-                    String encodedRedirectUri = URLEncoder.encode(urlStr, "UTF-8");
+                    urlStr =builder.toString();
+                    encodedRedirectUri = URLEncoder.encode(urlStr, "UTF-8");
                     log.info("urlStr==>"+urlStr);
                     log.info("encodedRedirectUri==>"+encodedRedirectUri);
-                    jumpUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+corpInfo.getCorpid()+"&redirect_uri="+ encodedRedirectUri +"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
+                    jumpUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+corpInfo.getCorpid()+"&redirect_uri="+ authUrl +"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
                     log.info("jumpUrl==>"+jumpUrl);
                 }
             }
-            else if ("plan/orderInsert".equals(pageRouter)) {
-                //费用报销
-                title = "收到新的插单计划";
-            }
-            else if(("plan/today".equals(pageRouter)||"plan/tomorrow".equals(pageRouter))&&corpUserid.split("|").length>1){
-                title="收到新的工作安排";
-            }
-            else if("plan/orderInsert".equals(pageRouter)){
-                title="收到新的插单计划";
-            }
-            else if("notReport".equals(pageRouter)){
-                title="报工未填报提醒";
-            }
-            jumpUrl = jumpUrl.replace("STATE", pageRouter);
+            jumpUrl = jumpUrl.replace("STATE", encodedRedirectUri.isEmpty()?pageRouter:encodedRedirectUri);
+            log.info("jumpUrl2==>"+jumpUrl);
             cardJson.put("title", title);
             cardJson.put("description", msg);
             cardJson.put("url", jumpUrl);