Sfoglia il codice sorgente

Merge branch 'nt-by-master' of http://192.168.0.43:8086/zh_bs/quality-inspection into nt-by-master

gaogao 2 settimane fa
parent
commit
41e1943427

+ 178 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/dao/ProjectWbsNodeDao.java

@@ -0,0 +1,178 @@
+package com.rongwei.bscommon.sys.dao;
+
+import com.alibaba.fastjson.JSONObject;
+import com.rongwei.bsentity.domain.ProjectWbsNodeDo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author dlc
+ * @since 2025-07-01
+ */
+public interface ProjectWbsNodeDao extends BaseMapper<ProjectWbsNodeDo> {
+
+    /**
+     * 获取所有的项目和机号
+     *
+     * @return
+     */
+    @Select("SELECT " +
+            " DISTINCT PROJECTID, " +
+            " MATHINECODE " +
+            "FROM " +
+            " PROJECT_WBS_NODE")
+    List<JSONObject> getProjectAndMachine();
+
+    @Update("UPDATE PROJECT_WBS_NODE T1  " +
+            " SET T1.STATE = (SELECT MAX(T2.INSTATE) INSTATE FROM ZHCX_ITP_PROJECT_NODE_STATE T2 WHERE T2.NODEID = T1.ITPNODEID and T2.PRJID=  #{projectId} and T2.MATHINECODE= #{machineNo})  " +
+            "where T1.PROJECTID=  #{projectId} and T1.MATHINECODE= #{machineNo}; " +
+            "update PROJECT_WBS_NODE set STATE='2' where (STATE='10' or STATE='30')   " +
+            "and PROJECTID=  #{projectId} and MATHINECODE= #{machineNo}; " +
+            "WITH min_complete_time AS ( " +
+            "    SELECT  " +
+            "        NODEID, " +
+            "        PRJID, " +
+            "        MATHINECODE, " +
+            "        MIN(INCOMPLETETIME) AS MIN_INCOMPLETETIME " +
+            "    FROM  " +
+            "        ZHCX_ITP_PROJECT_NODE_STATE " +
+            "    WHERE  " +
+            "        INSTATE IN (10, 30) and PRJID=  #{projectId} and MATHINECODE= #{machineNo} " +
+            "    GROUP BY  " +
+            "        NODEID, " +
+            "        PRJID, " +
+            "        MATHINECODE " +
+            ") " +
+            "UPDATE  " +
+            "    PROJECT_WBS_NODE pwn " +
+            "SET  " +
+            "    FACTENDDATE = ( " +
+            "        SELECT mct.MIN_INCOMPLETETIME " +
+            "        FROM min_complete_time mct " +
+            "        WHERE mct.NODEID = pwn.ITPNODEID " +
+            "          AND mct.PRJID = pwn.PROJECTID " +
+            "          AND mct.MATHINECODE = pwn.MATHINECODE " +
+            "    ) where STATE='2' and PROJECTID=  #{projectId} and MATHINECODE= #{machineNo}; " +
+            " " +
+            "UPDATE PROJECT_WBS_NODE T1 " +
+            "SET T1.STATEOUT= (SELECT MAX(T2.OUTSTATE) OUTSTATE FROM ZHCX_ITP_PROJECT_NODE_STATE T2 WHERE T2.NODEID = T1.ITPNODEID and T2.PRJID=  #{projectId} and T2.MATHINECODE= #{machineNo})  " +
+            "where T1.PROJECTID=  #{projectId} and T1.MATHINECODE= #{machineNo}; " +
+            "update PROJECT_WBS_NODE set STATEOUT='2' where (STATEOUT='10' or STATEOUT='30')  " +
+            "and PROJECTID=  #{projectId} and MATHINECODE= #{machineNo}")
+    void updateWbsNodeState(@Param("projectId") String projectId, @Param("machineNo") String machineNo);
+
+    /**
+     * 获取所有的多个报验点的任务
+     *
+     * @param projectId
+     * @param machineNo
+     * @return
+     */
+    @Select("select ID,ITPNODEID,TASKNAME from PROJECT_WBS_NODE T1 " +
+            "   where T1.PROJECTID=#{projectId} and T1.MATHINECODE=#{machineNo} " +
+            "   and  INSTR(ITPNODEID, ',') > 0")
+    List<JSONObject> getAllNode(@Param("projectId") String projectId, @Param("machineNo") String machineNo);
+
+    /**
+     * 更新进度
+     *
+     * @param projectId
+     * @param machineNo
+     */
+    @Update("WITH cte_calculation AS ( " +
+            " select f.pid as id,f.PLANSTARTDATE-g.PLANSTARTDATE pass,g.total, " +
+            " (f.PLANSTARTDATE-g.PLANSTARTDATE)/g.total as progress  " +
+            " from PROJECT_WBS_NODE a right join ( " +
+            " select PID,MAX(PLANSTARTDATE) PLANSTARTDATE from PROJECT_WBS_NODE   " +
+            " where PROJECTID=#{projectId} and MATHINECODE=#{machineNo} and (STATE = '1' or STATE='2') and DELETED='0' group by PID ) f  " +
+            " on a.ID=f.PID left join  " +
+            " (select PID,MIN(PLANSTARTDATE) PLANSTARTDATE,MAX(PLANSTARTDATE)-MIN(PLANSTARTDATE) total from PROJECT_WBS_NODE   " +
+            " where PROJECTID=#{projectId} and MATHINECODE=#{machineNo} and DELETED='0' group by PID) g  " +
+            " on a.ID = g.PID " +
+            "  WHERE g.total!=0  " +
+//            "-- 过滤无效日期 " +
+            " ) " +
+            " UPDATE PROJECT_WBS_NODE AS t " +
+            " SET progress = ROUND(c.progress * 100, 4) " +
+            " FROM cte_calculation c " +
+            " WHERE t.id = c.id; " +
+            "WITH child_date_diff AS ( " +
+            "    SELECT  " +
+            "        PID,MIN(PLANSTARTDATE) MINDATE, " +
+            "        MAX(PLANSTARTDATE) - MIN(PLANSTARTDATE) AS max_date_diff " +
+            "    FROM  " +
+            "        project_wbs_node  " +
+            "    WHERE  " +
+            "        TYPE='milestone' and DELETED='0' and PROJECTID=#{projectId} and MATHINECODE=#{machineNo} " +
+            "    GROUP BY  " +
+            "        PID " +
+            "), " +
+//            "-- 获取每个父节点下STATE为1或2的子节点最大PLANSTARTDATE " +
+            "valid_child_dates AS ( " +
+            "    SELECT distinct   " +
+            "        PID, " +
+            "        MAX(PLANSTARTDATE) AS max_valid_date " +
+            "    FROM  " +
+            "        project_wbs_node " +
+            "    WHERE  " +
+            "        STATE = '2' and " +
+            "        TYPE='milestone' and DELETED='0' AND PROJECTID=#{projectId} and MATHINECODE=#{machineNo} " +
+            "    GROUP BY  " +
+            "        PID " +
+            "), " +
+            " " +
+//            "-- 获取每个子节点的下一个PLANSTARTDATE " +
+            "next_node_dates AS ( " +
+            "    SELECT DISTINCT   " +
+            "        ID,PID,PLANSTARTDATE,FACTENDDATE, " +
+            "        LEAD(PLANSTARTDATE) OVER (PARTITION BY PID ORDER BY PLANSTARTDATE) AS next_date " +
+            "    FROM  " +
+            "        project_wbs_node where PROJECTID=#{projectId} and MATHINECODE=#{machineNo} " +
+            "), " +
+            " " +
+//            "-- 计算分子值(考虑当前时间与节点时间关系) " +
+            "numerator_calc AS ( " +
+            "    SELECT  " +
+            "        vcd.PID, " +
+            "        CASE " +
+            "            WHEN nnd.next_date IS NULL or nnd.FACTENDDATE is null THEN vcd.max_valid_date " +
+            "            WHEN now()- nnd.FACTENDDATE >= nnd.next_date-vcd.max_valid_date THEN nnd.next_date " +
+            "            WHEN now()- nnd.FACTENDDATE < nnd.next_date-vcd.max_valid_date THEN ADD_DAYS(vcd.max_valid_date, (now()- nnd.FACTENDDATE)) " +
+            "            ELSE vcd.max_valid_date " +
+            "        END AS numerator_value " +
+            "    FROM  " +
+            "        valid_child_dates vcd " +
+            "    JOIN  " +
+            "        next_node_dates nnd ON nnd.PLANSTARTDATE = vcd.max_valid_date AND nnd.PID = vcd.PID " +
+            ") " +
+            "UPDATE project_wbs_node pwn " +
+            "SET PROGRESS = ( " +
+            "    SELECT top 1   " +
+            "        CASE  " +
+            "            WHEN cdd.max_date_diff = 0 THEN 1 " +
+            "            ELSE DATEDIFF(DAY, cdd.MINDATE, nc.numerator_value) * 100 /  " +
+            "                 cdd.max_date_diff  " +
+            "        END " +
+            "    FROM  " +
+            "        numerator_calc nc " +
+            "    JOIN  " +
+            "        child_date_diff cdd ON nc.PID = cdd.PID " +
+            "    WHERE  " +
+            "        nc.PID = pwn.ID   " +
+            "        AND pwn.PROJECTID=#{projectId} and pwn.MATHINECODE=#{machineNo} " +
+            ") " +
+            "WHERE EXISTS ( " +
+            "    SELECT 1 " +
+            "    FROM numerator_calc nc " +
+            "    WHERE nc.PID = pwn.ID " +
+            ");")
+    void updateProgress(@Param("projectId") String projectId, @Param("machineNo") String machineNo);
+}

+ 19 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/dao/ZhcxPersistentManageDao.java

@@ -7,6 +7,7 @@ import com.rongwei.bsentity.domain.ZhcxCoreInspectionIndicatorsTemplateDo;
 import com.rongwei.bsentity.domain.ZhcxPersistentManageDo;
 import com.rongwei.bsentity.vo.OrganizationVo;
 import com.rongwei.bsentity.vo.PersistentVo;
+import com.rongwei.bsentity.vo.ZhcxPersistentManageVo;
 import com.rongwei.bsentity.vo.ZhcxPersistentWordVO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
@@ -28,6 +29,16 @@ public interface ZhcxPersistentManageDao extends BaseMapper<ZhcxPersistentManage
             "</script>")
     List<ZhcxPersistentManageDo> listData(Map<String, Object> map);
 
+    @Select("<script>select a.*,b.SORT from ZHCX_PERSISTENT_MANAGE a " +
+            "left join SYS_ORGANIZATION b on a.FIRSTORGID = b.ID " +
+            "where 1=1 and a.DELETED = '0' and a.PERIOD = #{period} and YEAR(a.CREATEDATE) = #{year} " +
+            "and a.FILL IS NOT NULL AND b.DELETED = '0' AND b.ORGTYPE = '20' " +
+            "<if test='params!=null and params!=null'>" +
+            " and ${params}" +
+            "</if>" +
+            "</script>")
+    List<ZhcxPersistentManageVo> listWzData(Map<String, Object> map);
+
     @Select("<script>select FIRSTORGNAME,TYPE,SUM(CASE WHEN PUNISHCONFIRMAMOUNT IS NOT NULL AND TYPE = '处罚' " +
             "THEN PUNISHCONFIRMAMOUNT ELSE AMOUNT END) AS AMOUNT,COUNT(*) AS COUNT from ZHCX_PERSISTENT_MANAGE " +
             "where 1=1 and DELETED = '0' and PERIOD = #{period} and YEAR(CREATEDATE) = #{year} " +
@@ -90,4 +101,12 @@ public interface ZhcxPersistentManageDao extends BaseMapper<ZhcxPersistentManage
 
     @Select("SELECT * FROM ZHCX_CHECK_BEFORE_QUALIFIED WHERE DELETED ='0'")
     List<ZhcxCheckBeforeQualifiedDo> getCheckBeforeQualifiedDos();
+
+    @Select("SELECT a.ISSUETYPE,b.FULLNAME AS ORGNAME, COUNT(a.TENANTID) AS CNT\n" +
+            "FROM ZHCX_PERSISTENT_MANAGE a \n" +
+            "LEFT JOIN SYS_ORGANIZATION b on a.TENANTID = b.ID \n"+
+            "WHERE a.DELETED = '0' AND a.TENANTID = #{tenantid} AND a.FILL = #{fill} \n" +
+            "AND TO_CHAR(a.CHECKDATE, 'YYYY-MM-DD') BETWEEN TO_DATE(#{startDate}, 'YYYY-MM-DD') AND TO_DATE(#{endDate}, 'YYYY-MM-DD')\n" +
+            "GROUP BY a.ISSUETYPE, a.TENANTID,b.FULLNAME")
+    List<Map<String, Object>> listGroupData(Map<String, Object> map);
 }

+ 21 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/service/ProjectWbsNodeService.java

@@ -0,0 +1,21 @@
+package com.rongwei.bscommon.sys.service;
+
+import com.rongwei.bsentity.domain.ProjectWbsNodeDo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author dlc
+ * @since 2025-07-01
+ */
+public interface ProjectWbsNodeService extends IService<ProjectWbsNodeDo> {
+
+    /**
+     * 更新wbs节点
+     *
+     */
+    void updateWbsNode();
+}

+ 3 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/service/ZhcxPersistentManageService.java

@@ -21,4 +21,7 @@ public interface ZhcxPersistentManageService extends IService<ZhcxPersistentMana
     void downloadReportData(Map<String, Object> map, HttpServletResponse response);
 
     void jyWordExport(Map<String, Object> map, HttpServletResponse response);
+
+    void issueExcelExport(Map<String, Object> map, HttpServletResponse response);
+
 }

+ 141 - 0
business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ProjectWbsNodeServiceImpl.java

@@ -0,0 +1,141 @@
+package com.rongwei.bscommon.sys.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.rongwei.bscommon.sys.service.ZhcxItpProjectNodeStateService;
+import com.rongwei.bsentity.domain.ProjectWbsNodeDo;
+import com.rongwei.bscommon.sys.dao.ProjectWbsNodeDao;
+import com.rongwei.bscommon.sys.service.ProjectWbsNodeService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.rongwei.bsentity.domain.ZhcxItpProjectNodeStateDo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author dlc
+ * @since 2025-07-01
+ */
+@Service
+public class ProjectWbsNodeServiceImpl extends ServiceImpl<ProjectWbsNodeDao, ProjectWbsNodeDo> implements ProjectWbsNodeService {
+
+    @Autowired
+    private ProjectWbsNodeDao dao;
+
+    @Autowired
+    private ZhcxItpProjectNodeStateService zhcxItpProjectNodeStateService;
+
+    /**
+     * 更新wbs节点
+     *
+     */
+    @Override
+    public void updateWbsNode() {
+        //获取项目机号
+        final List<JSONObject> prjMachineList = dao.getProjectAndMachine();
+
+        for(JSONObject row : prjMachineList) {
+            updateProjectWbs(row);
+        }
+    }
+
+    /**
+     * 更新单个项目
+     *
+     * @param projectMachineObj
+     */
+    private void updateProjectWbs(JSONObject projectMachineObj) {
+        //更新一个报验点的任务节点状态
+        final String projectid = projectMachineObj.getString("PROJECTID");
+        final String mathinecode = projectMachineObj.getString("MATHINECODE");
+        dao.updateWbsNodeState(projectid, mathinecode);
+
+        // 单个报验点更新完还需更新多个报验点,先获取项目所有的报验点状态
+        final LambdaQueryWrapper<ZhcxItpProjectNodeStateDo> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.eq(ZhcxItpProjectNodeStateDo::getPrjid, projectid)
+                .eq(ZhcxItpProjectNodeStateDo::getMathinecode, mathinecode);
+        final List<ZhcxItpProjectNodeStateDo> list = zhcxItpProjectNodeStateService.list(queryWrapper);
+
+        if(ObjectUtil.isEmpty(list)) { //无报验点不做处理
+            updateProgress(projectid, mathinecode);
+            return ;
+        }
+        final List<JSONObject> nodeList = dao.getAllNode(projectid, mathinecode); //获取所有任务报验点
+        if(ObjectUtil.isEmpty(nodeList)) { //无任务报验点不做处理
+            updateProgress(projectid, mathinecode);
+            return ;
+        }
+
+        //转换格式方便读取
+        Map<String, ZhcxItpProjectNodeStateDo> nodeStateMap = new HashMap<>(list.size());
+        for(ZhcxItpProjectNodeStateDo state : list) {
+            nodeStateMap.put(state.getNodeid(), state);
+        }
+
+        int scount = 0, count = 0;
+
+        String stateIn = "0", stateOut = "0";
+        int finishCnt = 0, finishCntOut = 0;
+        for(JSONObject item : nodeList) {
+            count = nodeList.size();//总共多报验点任务数量
+            final String itpnodeid = item.getString("ITPNODEID");
+            final String[] itpNodeIds = itpnodeid.split(",");
+            for(String nodeId : itpNodeIds) {
+                final ZhcxItpProjectNodeStateDo nodeState = nodeStateMap.get(nodeId);
+                if(ObjectUtil.isNull(nodeState)) {
+                    continue;
+                }
+
+                //内部
+                if("10".equals(nodeState.getInstate()) || "30".equals(nodeState.getInstate())) {
+                    finishCnt++;
+                }
+
+                //外部
+                if("10".equals(nodeState.getOutstate()) || "30".equals(nodeState.getOutstate())) {
+                    finishCntOut++;
+                    stateOut = "1";
+                }
+
+                if(finishCnt == itpNodeIds.length) {
+                    stateIn = "2";
+                } else if(finishCnt > 0) {
+                    stateIn = "1";
+                }
+
+                if(itpNodeIds.length > 1 && finishCntOut == itpNodeIds.length) {
+                    stateOut = "2";
+                }
+
+                //更新任务点状态
+                final LambdaUpdateWrapper<ProjectWbsNodeDo> updateWrapper = Wrappers.lambdaUpdate();
+                updateWrapper.eq(ProjectWbsNodeDo::getId, item.getString("ID"))
+                        .set(ProjectWbsNodeDo::getState, stateIn).set(ProjectWbsNodeDo::getStateout, stateOut);
+                update(updateWrapper);
+                scount++;
+
+                if(scount == scount) { //更新进度
+                    updateProgress(projectid, mathinecode);
+                }
+            }
+        }
+    }
+
+    /**
+     * 更新进度
+     *
+     */
+    private void updateProgress(String projectId, String machineNo) {
+        dao.updateProgress(projectId, machineNo);
+    }
+}

+ 44 - 38
business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ZhcxInsideInspectionServiceImpl.java

@@ -2357,56 +2357,62 @@ public class ZhcxInsideInspectionServiceImpl extends ServiceImpl<ZhcxInsideInspe
             return ;
         }
 
-        ZhcxInsideInspectionDo itpDo = inOper.getInspection();
+        ZhcxInsideInspectionDo inside = inOper.getInspection();
         String machineNo = inOper.getInspection().getMachineno();
         if (StringUtils.isBlank(machineNo)) {
             machineNo = inOper.getInspection().getStructuremachineno();
         }
         if (StringUtils.isBlank(machineNo)) {
-            log.error("{}-{}:总装机号和结构机号都没有", itpDo.getId(), itpDo.getInspectioncode());
+            log.error("{}-{}:总装机号和结构机号都没有", inside.getId(), inside.getInspectioncode());
             return;
         }
-        String[] machinenos = machineNo.split(",");
-        for (String mn : machinenos) {
-            LambdaQueryWrapper<ZhcxItpProjectNodeStateDo> queryWrapper = Wrappers.lambdaQuery();
-            queryWrapper.eq(ZhcxItpProjectNodeStateDo::getPrjid, itpDo.getProjectid())
-                    .eq(ZhcxItpProjectNodeStateDo::getMathinecode, mn)
-                    .eq(ZhcxItpProjectNodeStateDo::getNodeid, itpDo.getInspectioncontentid());
-            List<ZhcxItpProjectNodeStateDo> stateList = itpProjectNodeStateService.list(queryWrapper);
-            ZhcxItpProjectNodeStateDo stateDo = BusinessFunUtils.getPrjNodeState(stateList);
-
-            if(ObjectUtil.isNull(stateDo)) {
-                stateDo = new ZhcxItpProjectNodeStateDo();
-                stateDo.setId(SecurityUtil.getUUID());
-                stateDo.setMathinecode(mn);
-                stateDo.setPrjid(itpDo.getProjectid());
-                stateDo.setNodeid(itpDo.getInspectioncontentid());
-                stateDo.setDeleted("0");
-
-                stateDo.setCreatedate(inOper.getOperTime());
-                stateDo.setCreateuserid(inOper.getOperUser().getId());
-                stateDo.setCreateusername(inOper.getOperUser().getName());
+        String[] machinenos = machineNo.split(","); //机号
+        final String[] nodeIds = inside.getInspectioncontentid().split(","); //报验点id
+
+        for(String nodeId : nodeIds) { // 报验点
+            for (String mn : machinenos) { // 机号
+
+                //查询报验点状态表中
+                LambdaQueryWrapper<ZhcxItpProjectNodeStateDo> queryWrapper = Wrappers.lambdaQuery();
+                queryWrapper.eq(ZhcxItpProjectNodeStateDo::getPrjid, inside.getProjectid())
+                        .eq(ZhcxItpProjectNodeStateDo::getMathinecode, mn)
+                        .eq(ZhcxItpProjectNodeStateDo::getNodeid, nodeId);
+                List<ZhcxItpProjectNodeStateDo> stateList = itpProjectNodeStateService.list(queryWrapper);
+                ZhcxItpProjectNodeStateDo stateDo = BusinessFunUtils.getPrjNodeState(stateList);
+
+                if(ObjectUtil.isNull(stateDo)) {
+                    stateDo = new ZhcxItpProjectNodeStateDo();
+                    stateDo.setId(SecurityUtil.getUUID());
+                    stateDo.setMathinecode(mn);
+                    stateDo.setPrjid(inside.getProjectid());
+                    stateDo.setNodeid(nodeId);
+                    stateDo.setDeleted("0");
+
+                    stateDo.setCreatedate(inOper.getOperTime());
+                    stateDo.setCreateuserid(inOper.getOperUser().getId());
+                    stateDo.setCreateusername(inOper.getOperUser().getName());
 //                entity.setIncompletetime(itpDoPa.getInspectioncomplatetime());
-                assembleUpdateNodeState(stateDo, inOper, complateTime, false);
+                    assembleUpdateNodeState(stateDo, inOper, complateTime, false);
 
-                nodeStateBo.getInsertList().add(stateDo);
-            } else {
+                    nodeStateBo.getInsertList().add(stateDo);
+                } else {
 //                stateDo.setIncompletetime(itpDoPa.getInspectioncomplatetime());
-                assembleUpdateNodeState(stateDo, inOper, complateTime, true);
+                    assembleUpdateNodeState(stateDo, inOper, complateTime, true);
 
-                nodeStateBo.getUpdateList().add(stateDo);
-            }
+                    nodeStateBo.getUpdateList().add(stateDo);
+                }
 
-            // 报验点-内部报验单
-            ZhcxItpProjectNodeStateInsideDo stateInside = new ZhcxItpProjectNodeStateInsideDo();
-            stateInside.setId(SecurityUtil.getUUID());
-            stateInside.setDeleted("0");
-            stateInside.setInsideid(itpDo.getId());
-            stateInside.setStateid(stateDo.getId());
-            stateInside.setInspectioncode(itpDo.getInspectioncode());
-            stateInside.setLaunchtype(itpDo.getLaunchtype());
-            stateInside.setStateid(stateDo.getId());
-            nodeStateBo.getInsideStateList().add(stateInside);
+                // 报验点-内部报验单
+                ZhcxItpProjectNodeStateInsideDo stateInside = new ZhcxItpProjectNodeStateInsideDo();
+                stateInside.setId(SecurityUtil.getUUID());
+                stateInside.setDeleted("0");
+                stateInside.setInsideid(inside.getId());
+                stateInside.setStateid(stateDo.getId());
+                stateInside.setInspectioncode(inside.getInspectioncode());
+                stateInside.setLaunchtype(inside.getLaunchtype());
+                stateInside.setStateid(stateDo.getId());
+                nodeStateBo.getInsideStateList().add(stateInside);
+            }
         }
     }
 

+ 11 - 4
business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ZhcxMdfFormServiceImpl.java

@@ -22,6 +22,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.text.SimpleDateFormat;
+import java.time.LocalTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -56,10 +57,16 @@ public class ZhcxMdfFormServiceImpl extends ServiceImpl<ZhcxMdfFormDao, ZhcxMdfF
         R r = new R();
         if (dtwhoapproveTime == null || dtwhoapproveTime.length() == 0) {
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
-            Calendar calendar = Calendar.getInstance();
-            calendar.add(Calendar.DATE, -1);
-            Date yesterday = calendar.getTime();
-            dtwhoapproveTime = sdf.format(yesterday);
+            LocalTime currentTime = LocalTime.now();
+            LocalTime sevenAM = LocalTime.of(7, 0); // 早上7点
+            if (currentTime.isBefore(sevenAM)) {
+                Calendar calendar = Calendar.getInstance();
+                calendar.add(Calendar.DATE, -1);
+                Date yesterday = calendar.getTime();
+                dtwhoapproveTime = sdf.format(yesterday);
+            } else {
+                dtwhoapproveTime = sdf.format(new Date());
+            }
         }
         Map<String, Object> mdfmap = mdfApi.apiCall(dtwhoapproveTime);
         if (mdfmap.get("code").equals("200")) {

+ 235 - 68
business-common/src/main/java/com/rongwei/bscommon/sys/service/impl/ZhcxPersistentManageServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.aspose.cells.BorderType;
+import com.aspose.cells.SaveFormat;
 import com.aspose.cells.Style;
 import com.aspose.cells.*;
 import com.aspose.words.Cell;
@@ -20,17 +21,16 @@ import com.rongwei.bsentity.domain.*;
 import com.rongwei.bsentity.dto.PersistentDeptDto;
 import com.rongwei.bsentity.dto.ZhcxPersistentManageDto;
 import com.rongwei.bsentity.dto.ZhcxPersistentReportDto;
-import com.rongwei.bsentity.vo.FormDataVO;
-import com.rongwei.bsentity.vo.OrganizationVo;
-import com.rongwei.bsentity.vo.PersistentVo;
-import com.rongwei.bsentity.vo.ZhcxPersistentWordVO;
+import com.rongwei.bsentity.vo.*;
 import com.rongwei.rwadmincommon.system.domain.SysOrganizationDo;
 import com.rongwei.rwadmincommon.system.service.SysOrganizationService;
+import com.rongwei.rwcommon.base.R;
 import com.rongwei.rwcommon.base.exception.CustomException;
 import com.rongwei.rwcommon.utils.SecurityUtil;
 import com.rongwei.rwcommon.utils.StringUtils;
 import com.rongwei.rwcommoncomponent.excel.aspose.ExcelExportUtil;
 import com.rongwei.rwcommoncomponent.excel.aspose.ExcelUtils;
+import com.rongwei.rwcommoncomponent.excel.utils.ExcelHelpUtils;
 import com.rongwei.rwcommoncomponent.excel.utils.WordHelpUtils;
 import com.rongwei.rwcommoncomponent.excel.vo.FormData;
 import com.rongwei.rwcommoncomponent.file.service.SysFileItemService;
@@ -44,7 +44,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
 import javax.servlet.http.HttpServletResponse;
-import java.io.BufferedInputStream;
 import java.io.InputStream;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
@@ -55,7 +54,6 @@ import java.time.ZoneId;
 import java.time.temporal.WeekFields;
 import java.util.List;
 import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -83,6 +81,15 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
     private static final String DEPT_CODE = "0900";
     private static final Color[] COLORS = {Color.fromArgb(205, 223, 242),
             Color.fromArgb(249, 214, 194)};
+    private static final Map<String, Integer> defaultSortMap = new HashMap<>();
+    static {
+        defaultSortMap.put("钢构制造部", 2);
+        defaultSortMap.put("机电安装部", 3);
+        defaultSortMap.put("涂装管理部", 4);
+        defaultSortMap.put("调试管理部", 5);
+        defaultSortMap.put("重装项目部", 6);
+        defaultSortMap.put("供应链管理部", 7);
+    }
 
     @Override
     public void wordExport(Map<String, Object> map, HttpServletResponse response) {
@@ -101,7 +108,7 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
         String period = (String) periodObj;
         String year = (String) yearObj;
         map.put("period", "第" + period + "期");
-        List<ZhcxPersistentManageDo> list = zhcxPersistentManageDao.listData(map);
+        List<ZhcxPersistentManageVo> list = zhcxPersistentManageDao.listWzData(map);
         if (list.size() == 0) {
             throw new CustomException("当前周期暂无数据");
         }
@@ -144,52 +151,53 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
             mainMap.put("leftDate",reStartDate);
             mainMap.put("rightDate",reEndTime);
             mainMap.put("year",year);
-            Map<String, List<ZhcxPersistentManageDo>> collect =
+
+            // 1. 默认部门列表(ID → 名称)
+            Map<String, String> defaultDepts = new LinkedHashMap<>();
+            defaultDepts.put("1189640a3ef7407fa7c55e2a5903b356", "供应链管理部");
+            defaultDepts.put("7f6e7b9de969466fbea20aa86ab689c0", "重装项目部");
+            defaultDepts.put("4b1c0de60d84436696721b49d35b7f81", "调试管理部");
+            defaultDepts.put("13c7fc90d0b04eb199d7820e781866e8", "涂装管理部");
+            defaultDepts.put("25e37034d08f452682d957ab97154920", "机电安装部");
+            defaultDepts.put("060a72b5f74a4b44828d6149e296258d", "钢构制造部");
+
+            // 2. 实际数据分组
+            Map<String, List<ZhcxPersistentManageVo>> collect =
                     list.stream().collect(Collectors.groupingBy(ZhcxPersistentManageDo::getFirstorgid));
+
+            Set<String> handledDeptIds = new HashSet<>();
             List<PersistentDeptDto> deptDtoList = new ArrayList<>();
-            collect.forEach((k,v)->{
-                long param1 = v.stream()
-                        .filter(item -> !"0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid()))
-                        .count();
-                long param2 = v.stream()
-                        .filter(item -> !"0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid()))
-                        .filter(item -> "处罚".equals(item.getType()))
-                        .filter(item -> item.getAmount() != null && item.getAmount().compareTo(BigDecimal.ZERO) > 0)
-                        .count();
-                long param3 = v.stream()
-                        .filter(item -> "0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid()))
-                        .count();
-                long param4 = v.stream()
-                        .filter(item -> "0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid()))
-                        .filter(item -> "处罚".equals(item.getType()))
-                        .filter(item -> item.getAmount() != null && item.getAmount().compareTo(BigDecimal.ZERO) > 0)
-                        .count();
-                BigDecimal param5 = v.stream()
-                        .filter(item -> "处罚".equals(item.getType()))
-                        .map(ZhcxPersistentManageDo::getAmount)
-                        .filter(Objects::nonNull)
-                        .reduce(BigDecimal.ZERO, BigDecimal::add);
-                PersistentDeptDto dto = new PersistentDeptDto();
-                dto.setDutyDeptName(v.get(0).getFirstorgname());
-                dto.setSelfDeptCount(param1);
-                dto.setSelfDeptPunishCount(param2);
-                dto.setProductionCount(param3);
-                dto.setProductionPunishCount(param4);
-                dto.setPunishmentAmount(param5);
-                BigDecimal ratio = BigDecimal.ZERO;
-                ratio = BigDecimal.valueOf(param2)
-                        .divide(BigDecimal.valueOf(param1), 4, RoundingMode.HALF_UP)
-                        .multiply(BigDecimal.valueOf(100))
-                        .setScale(2, RoundingMode.HALF_UP);
-                dto.setRate(ratio);
-                deptDtoList.add(dto);
-            });
+
+            // 3. 先处理默认的6个
+            for (Map.Entry<String, String> entry : defaultDepts.entrySet()) {
+                String deptId = entry.getKey();
+                String deptName = entry.getValue();
+
+                List<ZhcxPersistentManageVo> v = collect.getOrDefault(deptId, Collections.emptyList());
+                deptDtoList.add(buildDeptDto(v, deptName));
+                handledDeptIds.add(deptId);
+            }
+
+            // 4. 再处理“额外的有数据的部门”
+            for (Map.Entry<String, List<ZhcxPersistentManageVo>> entry : collect.entrySet()) {
+                String deptId = entry.getKey();
+                if (handledDeptIds.contains(deptId)) {
+                    continue;
+                }
+
+                List<ZhcxPersistentManageVo> v = entry.getValue();
+                String deptName = v.get(0).getFirstorgname(); // 假设firstorgname都一致
+                deptDtoList.add(buildDeptDto(v, deptName));
+            }
             String deptNames = deptDtoList.stream()
                     .sorted(Comparator.comparing(PersistentDeptDto::getRate))
                     .limit(3)
                     .map(PersistentDeptDto::getDutyDeptName)
                     .collect(Collectors.joining("、"));
             mainMap.put("checkDept",deptNames);
+            deptDtoList = deptDtoList.stream()
+                    .sorted(Comparator.comparing(PersistentDeptDto::getSort, Comparator.nullsLast(Integer::compareTo)))
+                    .collect(Collectors.toList());
             if (deptDtoList.size() > 0) {
                 PersistentDeptDto totalDto = new PersistentDeptDto();
                 totalDto.setDutyDeptName("合计");
@@ -235,9 +243,9 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
             } catch (Exception e) {
                 e.printStackTrace();
             }
-            List<ZhcxPersistentManageDo> collect3 = list.stream().filter(item -> "0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid())
+            List<ZhcxPersistentManageVo> collect3 = list.stream().filter(item -> "0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid())
                             && "处罚".equals(item.getType()) && item.getAmount() != null && item.getAmount().compareTo(BigDecimal.ZERO) > 0)
-                    .sorted(Comparator.comparing(ZhcxPersistentManageDo::getFirstorgid))
+                    .sorted(Comparator.comparing(ZhcxPersistentManageVo::getFirstorgid))
                     .collect(Collectors.toList());
             if(collect3.size() >0){
                 try {
@@ -254,40 +262,66 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
             }
             try {
 
-                Map<String, List<ZhcxPersistentManageDo>> collect1 = list.stream().filter(item -> !"0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid())
+                Map<String, List<ZhcxPersistentManageVo>> collect1 = list.stream().filter(item -> !"0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid())
                                 && "处罚".equals(item.getType())
                                 && item.getAmount() != null && item.getAmount().compareTo(BigDecimal.ZERO) > 0)
                         .collect(Collectors.groupingBy(ZhcxPersistentManageDo::getFirstorgid));
                 SysFileItemDo fileItemDo3 = sysFileItemService.getById("b0c5f7b64f9a43bd88711c3c62d870ab");
-                collect1.forEach((k2,v2)->{
-                    Document doc3 = WordHelpUtils.getDoc(fileItemDo3.getFullpath());
-                    String firstorgname = v2.get(0).getFirstorgname();
+                List<DeptDocWrapperVo> docWrappers = new ArrayList<>();
+
+                // 默认 6 个
+                for (Map.Entry<String, String> entry : defaultDepts.entrySet()) {
+                    String deptId = entry.getKey();
+                    String deptName = entry.getValue();
+                    List<ZhcxPersistentManageVo> v2 = collect1.getOrDefault(deptId, Collections.emptyList());
+                    int sort = defaultSortMap.getOrDefault(deptName, 9999);
+                    docWrappers.add(new DeptDocWrapperVo(deptId, deptName, v2, sort));
+                }
+
+                // 额外的有数据的部门(排除已处理)
+                for (Map.Entry<String, List<ZhcxPersistentManageVo>> entry : collect1.entrySet()) {
+                    String deptId = entry.getKey();
+                    if (defaultDepts.containsKey(deptId)) {
+                        continue;
+                    }
+
+                    List<ZhcxPersistentManageVo> v2 = entry.getValue();
+                    String deptName = v2.get(0).getFirstorgname();
+                    int sort = 9999; // 非默认的部门放后面
+
+                    docWrappers.add(new DeptDocWrapperVo(deptId, deptName, v2, sort));
+                }
+
+                // 排序
+                docWrappers.sort(Comparator.comparingInt(DeptDocWrapperVo::getSort));
+                for (DeptDocWrapperVo wrapper : docWrappers) {
                     try {
-                        long pcount2 = v2.stream()
-                                .filter(item -> "处罚".equals(item.getType())
-                                        && item.getAmount() != null && item.getAmount().compareTo(BigDecimal.ZERO) > 0
-                                        && StringUtils.isNotBlank(item.getSitepic())).count();
-                        BigDecimal ppunishAmount2 = v2.stream()
-                                .filter(item -> "处罚".equals(item.getType()))
+                        Document doc3 = WordHelpUtils.getDoc(fileItemDo3.getFullpath());
+
+                        long pcount2 = wrapper.getData().stream()
+                                .filter(item -> StringUtils.isNotBlank(item.getSitepic()))
+                                .count();
+
+                        BigDecimal ppunishAmount2 = wrapper.getData().stream()
                                 .map(ZhcxPersistentManageDo::getAmount)
                                 .filter(Objects::nonNull)
                                 .reduce(BigDecimal.ZERO, BigDecimal::add);
+
                         doc3.getMailMerge().execute(
-                                new String[]{"picCount", "punishAmount",
-                                        "period", "topTime",
-                                        "year", "leftDate",
-                                        "rightDate", "checkStartDate", "checkEndDate","firstOrgName","bottomTime"},
-                                new Object[]{pcount2, ppunishAmount2,period,topTime,year,reStartDate,reEndTime,reStartTime,reEndTime,firstorgname,bottomTime}
+                                new String[]{"picCount", "punishAmount", "period", "topTime", "year",
+                                        "leftDate", "rightDate", "checkStartDate", "checkEndDate", "firstOrgName", "bottomTime"},
+                                new Object[]{pcount2, ppunishAmount2, period, topTime, year, reStartDate,
+                                        reEndTime, reStartTime, reEndTime, wrapper.getDeptName(), bottomTime}
                         );
+
                         DocumentBuilder builder = new DocumentBuilder(doc3);
                         builder.moveToDocumentEnd();
-                        createTable(builder,doc3,v2);
-                        doc.appendDocument(doc3,ImportFormatMode.KEEP_DIFFERENT_STYLES);
+                        createTable(builder, doc3, wrapper.getData());
+                        doc.appendDocument(doc3, ImportFormatMode.KEEP_DIFFERENT_STYLES);
                     } catch (Exception e) {
                         e.printStackTrace();
                     }
-                });
-
+                }
 
                 doc.updateFields();
                 response.setContentType("application/octet-stream;charset=ISO8859-1");
@@ -299,7 +333,55 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
             }
         }
     }
+    private PersistentDeptDto buildDeptDto(List<ZhcxPersistentManageVo> v, String deptName) {
+
+
+        long param1 = v.stream()
+                .filter(item -> !"0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid()))
+                .count();
+        long param2 = v.stream()
+                .filter(item -> !"0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid()))
+                .filter(item -> "处罚".equals(item.getType()))
+                .filter(item -> item.getAmount() != null && item.getAmount().compareTo(BigDecimal.ZERO) > 0)
+                .count();
+        long param3 = v.stream()
+                .filter(item -> "0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid()))
+                .count();
+        long param4 = v.stream()
+                .filter(item -> "0f11e70cd21843ee998a1ce5279028eb".equals(item.getBelongorgid()))
+                .filter(item -> "处罚".equals(item.getType()))
+                .filter(item -> item.getAmount() != null && item.getAmount().compareTo(BigDecimal.ZERO) > 0)
+                .count();
+        BigDecimal param5 = v.stream()
+                .filter(item -> "处罚".equals(item.getType()))
+                .map(ZhcxPersistentManageDo::getAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        BigDecimal ratio = BigDecimal.ZERO;
+        if (param1 > 0) {
+            ratio = BigDecimal.valueOf(param2)
+                    .divide(BigDecimal.valueOf(param1), 4, RoundingMode.HALF_UP)
+                    .multiply(BigDecimal.valueOf(100))
+                    .setScale(2, RoundingMode.HALF_UP);
+        }
 
+        PersistentDeptDto dto = new PersistentDeptDto();
+        if (!v.isEmpty()) {
+            dto.setSort(v.get(0).getSort());
+        } else {
+            dto.setSort(defaultSortMap.getOrDefault(deptName, 9999)); // 未知的默认到最后
+        }
+        dto.setDutyDeptName(deptName);
+        dto.setSelfDeptCount(param1);
+        dto.setSelfDeptPunishCount(param2);
+        dto.setProductionCount(param3);
+        dto.setProductionPunishCount(param4);
+        dto.setPunishmentAmount(param5);
+        dto.setRate(ratio);
+
+        return dto;
+    }
     @Override
     public void syncWzPlatform(List<String> ids) {
         //zhcxPersistentManageDao.syncWzDataUrl
@@ -537,6 +619,91 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
         }
     }
 
+    @Override
+    public void issueExcelExport(Map<String, Object> map, HttpServletResponse response) {
+        Object typeObj = map.get("type");
+        if( ObjectUtil.isEmpty(typeObj)){
+            throw  new CustomException("导出报错,请联系管理员");
+        }
+        String type = (String) typeObj;
+        int maxRow = 31;
+        SysFileItemDo fileItemDo = null;
+        if ("油漆".equals(type)) {
+            map.put("fill","油漆保护专项");
+            fileItemDo = sysFileItemService.getById("55edd353b7ae4035bcb0dfa148d6ecae");
+        }else if("焊接".equals(type)){
+            map.put("fill","焊接通病治理");
+            fileItemDo = sysFileItemService.getById("c34b09e16d1c48c6a40f92d19f7a2397");
+            maxRow = 26;
+        }
+        List<Map<String, Object>> result = zhcxPersistentManageDao.listGroupData(map);
+        Map<String, Map<String, Integer>> pivotData = new LinkedHashMap<>();
+
+        for (Map<String, Object> row : result) {
+            String issueType = (String) row.get("ISSUETYPE");
+            String orgName = (String) row.get("ORGNAME");
+            Integer count = ((Number) row.get("CNT")).intValue();
+
+            //orgNames.add(orgName); // 收集所有列名
+
+            pivotData.putIfAbsent(issueType, new HashMap<>());
+            pivotData.get(issueType).put(orgName, count);
+        }
+
+
+        try {
+            if (!excelUtils.GetLicense()) {
+                throw new CustomException("获取license异常");
+            }
+            Workbook wb = ExcelHelpUtils.getWorkbook(fileItemDo.getFullpath());
+            Worksheet sheet = wb.getWorksheets().get(0);
+            Cells cells = sheet.getCells();
+            // 读取公司列映射(第 2 行)
+            Map<String, Integer> companyColMap = new HashMap<>();
+            int maxCol = 9;
+            for (int col = 3; col <= maxCol; col++) {
+                String companyName = cells.get(1, col).getStringValue().trim();
+                if (!companyName.isEmpty()) {
+                    companyColMap.put(companyName, col);
+                }
+            }
+
+            // 读取类型行映射(第 0 列)
+            Map<String, Integer> typeRowMap = new HashMap<>();
+            for (int row = 2; row <= maxRow; row++) {
+                String issueType = cells.get(row, 0).getStringValue().trim();
+                if (!issueType.isEmpty()) {
+                    typeRowMap.put(issueType, row);
+                }
+            }
+            for (Map.Entry<String, Map<String, Integer>> issueTypeEntry : pivotData.entrySet()) {
+                String issueType = issueTypeEntry.getKey();
+                Integer row = typeRowMap.get(issueType);
+                if (row == null) {
+                    continue; // 模板中没有该类型,跳过
+                }
+
+                for (Map.Entry<String, Integer> companyEntry : issueTypeEntry.getValue().entrySet()) {
+                    String company = companyEntry.getKey();
+                    Integer col = companyColMap.get(company);
+                    if (col == null) {
+                        continue; // 模板中没有该公司,跳过
+                    }
+
+                    cells.get(row, col).putValue(companyEntry.getValue());
+                }
+            }
+            response.addHeader("Pargam", "no-cache");
+            response.addHeader("Cache-Control", "no-cache");
+            response.setContentType("application/octet-stream;charset=ISO8859-1");
+            response.setHeader("Content-Disposition", "attachment;filename=顽症.xlsx");
+            wb.save(response.getOutputStream(), SaveFormat.XLSX);
+            wb.dispose();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
     private void buildHeader(Cells cells) {
         cells.merge(0, 0, 2, 1);
         cells.get(0, 0).setValue("月份");
@@ -742,7 +909,7 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
     public static int I = 0;
     public static int Q = 0;
 
-    private void createTable(DocumentBuilder builder, Document doc, List<ZhcxPersistentManageDo> dataList) throws Exception {
+    private void createTable(DocumentBuilder builder, Document doc, List<ZhcxPersistentManageVo> dataList) throws Exception {
         // 动态复制模板表格
 
         int idx2 = 0;
@@ -769,7 +936,7 @@ public class ZhcxPersistentManageServiceImpl extends ServiceImpl<ZhcxPersistentM
      * @Description: 向已有表格模板插入数据
      * @Param: doc、index、List<GxyItemData>
      */
-    private void addexcel(Document doc, String k, int index, List<ZhcxPersistentManageDo> staff) throws Exception {
+    private void addexcel(Document doc, String k, int index, List<ZhcxPersistentManageVo> staff) throws Exception {
         Table table = (Table) doc.getChild(NodeType.TABLE, index, true);
         Range titleRange = table.getFirstRow().getRange();
 

+ 275 - 0
business-entity/src/main/java/com/rongwei/bsentity/domain/ProjectWbsNodeDo.java

@@ -0,0 +1,275 @@
+package com.rongwei.bsentity.domain;
+
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.rongwei.rwcommon.base.BaseDo;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author dlc
+ * @since 2025-07-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+@TableName("PROJECT_WBS_NODE")
+public class ProjectWbsNodeDo extends BaseDo {
+
+    private static final long serialVersionUID=1L;
+
+    /**
+     * 主键
+     */
+    @TableField("ID")
+    private String id;
+    /**
+     * 父节点ID
+     */
+    @TableField("PID")
+    private String pid;
+    /**
+     * 任务编号
+     */
+    @TableField("TASKCODE")
+    private String taskcode;
+    /**
+     * 任务标题
+     */
+    @TableField("TASKNAME")
+    private String taskname;
+    /**
+     * 全路径ID
+     */
+    @TableField("FULLID")
+    private String fullid;
+    /**
+     * 项目ID
+     */
+    @TableField("PROJECTID")
+    private String projectid;
+    /**
+     * 模版ID
+     */
+    @TableField("TMPID")
+    private String tmpid;
+    /**
+     * 模版名称
+     */
+    @TableField("TMPNAME")
+    private String tmpname;
+    /**
+     * 责任部门ID
+     */
+    @TableField("BELONGDEPTID")
+    private String belongdeptid;
+    /**
+     * 责任部门
+     */
+    @TableField("BELONGDEPTNAME")
+    private String belongdeptname;
+    /**
+     * 责任人ID
+     */
+    @TableField("DUTYUSERID")
+    private String dutyuserid;
+    /**
+     * 责任人
+     */
+    @TableField("DUTYUSERNAME")
+    private String dutyusername;
+    /**
+     * 任务附件
+     */
+    @TableField("ATTACHMENTS")
+    private String attachments;
+    /**
+     * 任务状态
+     */
+    @TableField("STATE")
+    private String state;
+    /**
+     * 任务优先级
+     */
+    @TableField("PRIORITY")
+    private String priority;
+    /**
+     * 任务类型
+     */
+    @TableField("TYPE")
+    private String type;
+    /**
+     * 是否已完成
+     */
+    @TableField("ISDONE")
+    private Integer isdone;
+    /**
+     * 任务进度
+     */
+    @TableField("PROGRESS")
+    private BigDecimal progress;
+    /**
+     * 是否生效
+     */
+    @TableField("ENABLED")
+    private String enabled;
+    /**
+     * 扩展信息
+     */
+    @TableField("ROPTIONS")
+    private String roptions;
+    /**
+     * 全路径ID
+     */
+    @TableField("FULLPID")
+    private String fullpid;
+    /**
+     * 层级
+     */
+    @TableField("LEVEL")
+    private Integer level;
+    /**
+     * 叶子节点
+     */
+    @TableField("ISLEAF")
+    private String isleaf;
+    /**
+     * 租户ID
+     */
+    @TableField("TENANTID")
+    private String tenantid;
+    /**
+     * 复制源任务ID
+     */
+    @TableField("SOURCEID")
+    private String sourceid;
+    /**
+     * 计划开始时间
+     */
+    @TableField("PLANSTARTDATE")
+    private Date planstartdate;
+    /**
+     * 计划结束时间
+     */
+    @TableField("PLANENDDATE")
+    private Date planenddate;
+    /**
+     * 实际开始时间
+     */
+    @TableField("FACTSTARTDATE")
+    private Date factstartdate;
+    /**
+     * 实际结束时间
+     */
+    @TableField("FACTENDDATE")
+    private Date factenddate;
+    /**
+     * 工程量
+     */
+    @TableField("NEEDQTYS")
+    private Integer needqtys;
+    /**
+     * 工期
+     */
+    @TableField("DURATION")
+    private Integer duration;
+    /**
+     * 权重
+     */
+    @TableField("BALANCE")
+    private BigDecimal balance;
+    /**
+     * 排序
+     */
+    @TableField("SORTINDEX")
+    private BigDecimal sortindex;
+    /**
+     * 关联机号
+     */
+    @TableField("MATHINECODE")
+    private String mathinecode;
+    /**
+     * 进度占比
+     */
+    @TableField("PROGRESSPERCENTAGE")
+    private BigDecimal progresspercentage;
+    /**
+     * 实际进度
+     */
+    @TableField("ACTUALPROGRESS")
+    private BigDecimal actualprogress;
+    /**
+     * 项目计划进度
+     */
+    @TableField("PROJECTPROGRESS")
+    private BigDecimal projectprogress;
+    /**
+     * 项目实际进度
+     */
+    @TableField("PROJECTACTUALPROGRESS")
+    private BigDecimal projectactualprogress;
+    /**
+     * 进度更新日期
+     */
+    @TableField("PROGRESSUPDATEDATE")
+    private Date progressupdatedate;
+    /**
+     * 计划进度
+     */
+    @TableField("PLANPROGRESS")
+    private BigDecimal planprogress;
+    /**
+     * 关联任务ID
+     */
+    @TableField("RELATETASKID")
+    private String relatetaskid;
+    /**
+     * 关联任务名称
+     */
+    @TableField("RELATETASKNAME")
+    private String relatetaskname;
+    /**
+     * 关联约束类型
+     */
+    @TableField("RELATETYPE")
+    private String relatetype;
+    /**
+     * ITP报验点ID
+     */
+    @TableField("ITPNODEID")
+    private String itpnodeid;
+    /**
+     * 关联ITP节点
+     */
+    @TableField("ITPNODENAME")
+    private String itpnodename;
+    /**
+     * 任务分类
+     */
+    @TableField("ABTYPE")
+    private String abtype;
+    /**
+     * 关联天数
+     */
+    @TableField("RELATEDAYS")
+    private Integer relatedays;
+    /**
+     * 外部报验状态
+     */
+    @TableField("STATEOUT")
+    private String stateout;
+    /**
+     * 是否外部报验
+     */
+    @TableField("NEEDOUT")
+    private String needout;
+
+
+}

+ 3 - 0
business-entity/src/main/java/com/rongwei/bsentity/dto/PersistentDeptDto.java

@@ -30,4 +30,7 @@ public class PersistentDeptDto {
 
     @JsonIgnore
     private BigDecimal rate;
+
+    @JsonIgnore
+    private Integer sort;
 }

+ 21 - 0
business-entity/src/main/java/com/rongwei/bsentity/vo/DeptDocWrapperVo.java

@@ -0,0 +1,21 @@
+package com.rongwei.bsentity.vo;
+
+import com.rongwei.bsentity.domain.ZhcxPersistentManageDo;
+import lombok.Data;
+
+import java.util.List;
+@Data
+public class DeptDocWrapperVo {
+
+    String deptId;
+    String deptName;
+    List<ZhcxPersistentManageVo> data;
+    int sort;
+
+    public DeptDocWrapperVo(String deptId, String deptName, List<ZhcxPersistentManageVo> data, int sort) {
+        this.deptId = deptId;
+        this.deptName = deptName;
+        this.data = data;
+        this.sort = sort;
+    }
+}

+ 10 - 0
business-entity/src/main/java/com/rongwei/bsentity/vo/ZhcxPersistentManageVo.java

@@ -0,0 +1,10 @@
+package com.rongwei.bsentity.vo;
+
+import com.rongwei.bsentity.domain.ZhcxPersistentManageDo;
+import lombok.Data;
+
+@Data
+public class ZhcxPersistentManageVo extends ZhcxPersistentManageDo {
+
+    private Integer sort;
+}

+ 36 - 0
business-server/src/main/java/com/rongwei/bsserver/controller/ProjectWbsNodeController.java

@@ -0,0 +1,36 @@
+package com.rongwei.bsserver.controller;
+
+
+import com.rongwei.bscommon.sys.service.ProjectWbsNodeService;
+import com.rongwei.rwcommon.base.R;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author dlc
+ * @since 2025-07-01
+ */
+@RestController
+@RequestMapping("/projectWbsNode")
+public class ProjectWbsNodeController {
+
+    @Autowired
+    private ProjectWbsNodeService service;
+
+    /**
+     * 更新节点
+     *
+     * @return
+     */
+    @PostMapping("/updateWbsNode")
+    @ResponseBody
+    public R updateWbsNode() {
+        service.updateWbsNode();
+        return R.ok();
+    }
+}
+

+ 9 - 0
business-server/src/main/java/com/rongwei/bsserver/controller/ZhcxPersistentController.java

@@ -79,4 +79,13 @@ public class ZhcxPersistentController {
     public void saveDeptUserCount(){
         zhcxPersistentManageService.saveDeptUserCount();
     }
+
+    /**
+     * 问题类型导出
+     */
+    @PostMapping("/issueExcelExport")
+    public void issueExcelExport(@RequestBody Map<String,Object> map , HttpServletResponse response){
+        zhcxPersistentManageService.issueExcelExport(map,response);
+    }
+
 }