瀏覽代碼

车间工单同步,工时管家增加人员特殊日期填报设置

QuYueTing 2 天之前
父節點
當前提交
bfdc57c43a

+ 65 - 62
fhKeeper/formulahousekeeper/collectdata/src/main/java/com/management/collectdata/controller/DataCollectController.java

@@ -479,11 +479,14 @@ public class DataCollectController {
 
 
     @RequestMapping("/getLeaveSheetDataSum")
-    public String getLeaveSheetDataSum() {
-        String sqlCount = "select count(*) from att_holiday_leave_order where audit_status = 3 and is_delete = 0 and ahlo.total_day > 0 and create_date >= DATE_SUB(CURDATE(), INTERVAL 14 DAY)";
+    public String getLeaveSheetDataSum(String startDate, String endDate) {
+        String sqlCount = "select count(*) from att_holiday_leave_order where audit_status = 3 and is_delete = 0 and total_day > 0 " +
+                "and date_format(begin_date,'%Y-%m-%d') between ? and ?";
         int totalCount = 0;
         try (Connection connection = mysqlDataSource.getConnection()) {
             PreparedStatement countStmt = connection.prepareStatement(sqlCount);
+            countStmt.setString(1, startDate);
+            countStmt.setString(2, endDate);
             ResultSet countRs = countStmt.executeQuery();
             if (countRs.next()) {
                 totalCount = countRs.getInt(1);
@@ -494,66 +497,66 @@ public class DataCollectController {
         }
         return String.valueOf(totalCount);
     }
-
-    @RequestMapping("/getLeaveSheetDataList")
-    public List<LeaveSheet> getLeaveSheetDataList(@RequestBody PageBO pageBO) {
-        String sqlQuery = "select distinct ahlo.id,ahlo.company_id,ahlo.emp_no,ahlo.emp_name " +
-                " ,ahlo.begin_date,ahlo.end_date,ahlo.leave_category_name " +
-                " ,ahlo.audit_status,ahlo.reason, eic.emp_no as operator_id " +
-                " ,ahlo.total_hour,ahlo.total_day,eie.mobile " +
-                " from att_holiday_leave_order ahlo " +
-                " left join emp_info eie on ahlo.emp_origin_id = eie.origin_id " +
-                " left join emp_info eic on ahlo.create_id = eic.origin_id " +
-                " where ahlo.audit_status = 3 and ahlo.is_delete = 0 and ahlo.total_day > 0 and ahlo.create_date >= DATE_SUB(CURDATE(), INTERVAL 14 DAY) order by ahlo.id limit ?,? ";
-        SimpleDateFormat sdfAll = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        SimpleDateFormat sdfYmd = new SimpleDateFormat("yyyy-MM-dd");
-        List<LeaveSheet> resList = new ArrayList<>();
-        try (Connection connection = mysqlDataSource.getConnection()) {
-            PreparedStatement queryStmt = connection.prepareStatement(sqlQuery);
-            int pageSize = pageBO.getPageSize();
-            int offset = pageBO.getPageNo();
-            queryStmt.setInt(1, offset);
-            queryStmt.setInt(2, pageSize);
-            try (ResultSet resultSet = queryStmt.executeQuery()) {
-                while (resultSet.next()) {
-                    LeaveSheet leaveSheet = new LeaveSheet();
-                    leaveSheet.setCompanyId(companyId);
-                    leaveSheet.setOwnerId(resultSet.getString("emp_no"));
-                    leaveSheet.setOwnerName(resultSet.getString("emp_name"));
-                    leaveSheet.setStartDate(null==resultSet.getDate("begin_date")?null:LocalDate.parse(sdfYmd.format(resultSet.getDate("begin_date")),DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-                    leaveSheet.setEndDate(null==resultSet.getDate("end_date")?null:LocalDate.parse(sdfYmd.format(resultSet.getDate("end_date")),DateTimeFormatter.ofPattern("yyyy-MM-dd")));
-                    switch (resultSet.getString("leave_category_name")){
-                        case "调休假" : leaveSheet.setLeaveType(6); break;
-                        case "年假" : leaveSheet.setLeaveType(2); break;
-                        case "事假" : leaveSheet.setLeaveType(0); break;
-                        case "病假" : leaveSheet.setLeaveType(1);break;
-                        case "婚假" : leaveSheet.setLeaveType(4);break;
-                        case "产假" : leaveSheet.setLeaveType(3);break;
-                        case "哺乳假" : leaveSheet.setLeaveType(3);break;
-                        case "陪产假" : leaveSheet.setLeaveType(7);break;
-                        case "丧假" : leaveSheet.setLeaveType(5);break;
-                        case "工伤假" : leaveSheet.setLeaveType(1);break;
-                        case "育儿假" : leaveSheet.setLeaveType(3);break;
-                        case "福利病假" : leaveSheet.setLeaveType(1);break;
-                        default: leaveSheet.setLeaveType(8);break;
-                    }
-                    leaveSheet.setStatus(0);
-                    leaveSheet.setRemark(resultSet.getString("reason"));
-                    leaveSheet.setOperatorId(resultSet.getString("operator_id"));
-                    leaveSheet.setTimeHours(null==resultSet.getBigDecimal("total_hour")?null:resultSet.getBigDecimal("total_hour").setScale(1,RoundingMode.HALF_UP).floatValue());
-                    leaveSheet.setTimeDays(null==resultSet.getBigDecimal("total_day")?null:resultSet.getBigDecimal("total_day").setScale(0,RoundingMode.HALF_UP).floatValue());
-                    leaveSheet.setIndate(LocalDateTime.now());
-                    leaveSheet.setTimeType(0);
-                    leaveSheet.setTel(resultSet.getString("mobile"));
-                    leaveSheet.setProcinstId(resultSet.getString("id"));
-                    resList.add(leaveSheet);
-                }
-            }
-        } catch (SQLException e) {
-            System.err.println("数据库操作错误: " + e.getMessage());
-        }
-        return resList;
-    }
+//
+//    @RequestMapping("/getLeaveSheetDataList")
+//    public List<LeaveSheet> getLeaveSheetDataList(@RequestBody PageBO pageBO) {
+//        String sqlQuery = "select distinct ahlo.id,ahlo.company_id,ahlo.emp_no,ahlo.emp_name " +
+//                " ,ahlo.begin_date,ahlo.end_date,ahlo.leave_category_name " +
+//                " ,ahlo.audit_status,ahlo.reason, eic.emp_no as operator_id " +
+//                " ,ahlo.total_hour,ahlo.total_day,eie.mobile " +
+//                " from att_holiday_leave_order ahlo " +
+//                " left join emp_info eie on ahlo.emp_origin_id = eie.origin_id " +
+//                " left join emp_info eic on ahlo.create_id = eic.origin_id " +
+//                " where ahlo.audit_status = 3 and ahlo.is_delete = 0 and ahlo.total_day > 0 and ahlo.create_date >= DATE_SUB(CURDATE(), INTERVAL 14 DAY) order by ahlo.id limit ?,? ";
+//        SimpleDateFormat sdfAll = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//        SimpleDateFormat sdfYmd = new SimpleDateFormat("yyyy-MM-dd");
+//        List<LeaveSheet> resList = new ArrayList<>();
+//        try (Connection connection = mysqlDataSource.getConnection()) {
+//            PreparedStatement queryStmt = connection.prepareStatement(sqlQuery);
+//            int pageSize = pageBO.getPageSize();
+//            int offset = pageBO.getPageNo();
+//            queryStmt.setInt(1, offset);
+//            queryStmt.setInt(2, pageSize);
+//            try (ResultSet resultSet = queryStmt.executeQuery()) {
+//                while (resultSet.next()) {
+//                    LeaveSheet leaveSheet = new LeaveSheet();
+//                    leaveSheet.setCompanyId(companyId);
+//                    leaveSheet.setOwnerId(resultSet.getString("emp_no"));
+//                    leaveSheet.setOwnerName(resultSet.getString("emp_name"));
+//                    leaveSheet.setStartDate(null==resultSet.getDate("begin_date")?null:LocalDate.parse(sdfYmd.format(resultSet.getDate("begin_date")),DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+//                    leaveSheet.setEndDate(null==resultSet.getDate("end_date")?null:LocalDate.parse(sdfYmd.format(resultSet.getDate("end_date")),DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+//                    switch (resultSet.getString("leave_category_name")){
+//                        case "调休假" : leaveSheet.setLeaveType(6); break;
+//                        case "年假" : leaveSheet.setLeaveType(2); break;
+//                        case "事假" : leaveSheet.setLeaveType(0); break;
+//                        case "病假" : leaveSheet.setLeaveType(1);break;
+//                        case "婚假" : leaveSheet.setLeaveType(4);break;
+//                        case "产假" : leaveSheet.setLeaveType(3);break;
+//                        case "哺乳假" : leaveSheet.setLeaveType(3);break;
+//                        case "陪产假" : leaveSheet.setLeaveType(7);break;
+//                        case "丧假" : leaveSheet.setLeaveType(5);break;
+//                        case "工伤假" : leaveSheet.setLeaveType(1);break;
+//                        case "育儿假" : leaveSheet.setLeaveType(3);break;
+//                        case "福利病假" : leaveSheet.setLeaveType(1);break;
+//                        default: leaveSheet.setLeaveType(8);break;
+//                    }
+//                    leaveSheet.setStatus(0);
+//                    leaveSheet.setRemark(resultSet.getString("reason"));
+//                    leaveSheet.setOperatorId(resultSet.getString("operator_id"));
+//                    leaveSheet.setTimeHours(null==resultSet.getBigDecimal("total_hour")?null:resultSet.getBigDecimal("total_hour").setScale(1,RoundingMode.HALF_UP).floatValue());
+//                    leaveSheet.setTimeDays(null==resultSet.getBigDecimal("total_day")?null:resultSet.getBigDecimal("total_day").setScale(0,RoundingMode.HALF_UP).floatValue());
+//                    leaveSheet.setIndate(LocalDateTime.now());
+//                    leaveSheet.setTimeType(0);
+//                    leaveSheet.setTel(resultSet.getString("mobile"));
+//                    leaveSheet.setProcinstId(resultSet.getString("id"));
+//                    resList.add(leaveSheet);
+//                }
+//            }
+//        } catch (SQLException e) {
+//            System.err.println("数据库操作错误: " + e.getMessage());
+//        }
+//        return resList;
+//    }
 
     @RequestMapping("/getLeaveSheetDataListInRange")
     public List<LeaveSheet> getLeaveSheetDataListInRange(@RequestBody PageBO pageBO) {

+ 426 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserCorpwxTimeController.java

@@ -884,5 +884,430 @@ public class UserCorpwxTimeController {
 
         return msg;
     }
-}
 
+    /**
+     * 导入Excel工时数据并与系统内填报的工时进行比对和更新
+     * @param multipartFile Excel文件
+     * @param request HTTP请求
+     * @return 处理结果
+     */
+    @RequestMapping("/importAndCompareWorktime")
+    public HttpRespMsg importAndCompareWorktime(MultipartFile multipartFile, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        // 固定处理公司ID为7544的数据
+        Integer companyId = 7544;
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
+
+        String fileName = multipartFile.getOriginalFilename();
+        File file = new File(fileName == null ? "file" : fileName);
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        
+        try {
+            inputStream = multipartFile.getInputStream();
+            outputStream = new FileOutputStream(file);
+            byte[] buffer = new byte[4096];
+            int temp = 0;
+            while ((temp = inputStream.read(buffer, 0, 4096)) != -1) {
+                outputStream.write(buffer, 0, temp);
+            }
+            inputStream.close();
+            outputStream.close();
+            
+            // 解析Excel文件
+            Workbook workbook = WorkbookFactory.create(new FileInputStream(file));
+            
+            // 获取公司全部成员
+            List<User> allUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+            
+            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/M/d");
+            
+            List<UserCorpwxTime> importedDataList = new ArrayList<>();
+            
+            // 遍历所有sheet(每个sheet代表一个月)
+            for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
+                Sheet sheet = workbook.getSheetAt(sheetIndex);
+                String sheetName = sheet.getSheetName();
+                System.out.println("正在处理Sheet: " + sheetName);
+                
+                if (sheet.getLastRowNum() == 0) {
+                    continue;
+                }
+                
+                // 解析每个sheet的数据
+                parseSheetData(sheet, sheetName, allUserList, importedDataList, companyId, sdf);
+                //以下正式运行时需要注释掉,测试的时候只测试第一个表单
+                if (sheetIndex > 0) {
+                    break;
+                }
+            }
+            
+            if (importedDataList.isEmpty()) {
+                msg.setError("未找到有效的工时数据");
+                return msg;
+            }
+
+            System.out.println("找到有效工时数据size=" + importedDataList.size());
+            // 比对和更新工时数据
+            compareAndUpdateWorktime(importedDataList, companyId);
+            
+            System.out.println("工时数据导入和比对完成,共处理 " + importedDataList.size() + " 条记录");
+            
+        } catch (IOException e) {
+            e.printStackTrace();
+            msg.setError("文件处理出错");
+            return msg;
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            msg.setError("数据格式有误或存在空数据 导入失败");
+            return msg;
+        } catch (InvalidFormatException e) {
+            e.printStackTrace();
+            msg.setError("文件格式错误,如果安装了加密软件需要先解密再上传");
+            return msg;
+        } catch (EncryptedDocumentException e) {
+            e.printStackTrace();
+            msg.setError("文件加密状态,需要先解除加密状态再上传");
+            return msg;
+        } catch (Exception e) {
+            e.printStackTrace();
+            msg.setError("发生其他错误:" + e.getMessage());
+            return msg;
+        } finally {
+            try {
+                if (outputStream != null && inputStream != null) {
+                    outputStream.close();
+                    inputStream.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            file.delete();
+        }
+        
+        return msg;
+    }
+    
+    /**
+     * 解析单个Sheet的数据
+     */
+    private void parseSheetData(Sheet sheet, String sheetName, List<User> allUserList, 
+                               List<UserCorpwxTime> importedDataList, Integer companyId, SimpleDateFormat sdf) {
+        
+        // 获取年月信息
+        String yearMonth = extractYearMonth(sheetName);
+        if (yearMonth == null) {
+            System.out.println("无法解析Sheet名称中的年月信息: " + sheetName);
+            return;
+        }
+        
+        Row headerRow = sheet.getRow(0);
+        if (headerRow == null) {
+            return;
+        }
+        
+        // 解析日期列(从第3列开始,前两列是姓名和部门)
+        List<LocalDate> dateColumns = new ArrayList<>();
+        for (int colIndex = 2; colIndex < headerRow.getLastCellNum(); colIndex++) {
+            Cell cell = headerRow.getCell(colIndex);
+            if (cell != null) {
+                String cellValue = cell.toString().trim();
+                System.out.println("cellValue=="+cellValue);
+                if (cellValue.matches("\\d+(\\.0)?")) {
+                    try {
+                        int day = (int) Double.parseDouble(cellValue);
+                        LocalDate date = LocalDate.of(Integer.parseInt(yearMonth.substring(0, 4)), 
+                                                    Integer.parseInt(yearMonth.substring(4, 6)), day);
+                        System.out.println("解析出来date="+date);
+                        dateColumns.add(date);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        dateColumns.add(null);
+                    }
+                } else {
+                    dateColumns.add(null);
+                }
+            } else {
+                dateColumns.add(null);
+            }
+        }
+        System.out.println(dateColumns);
+        
+        // 收集所有员工姓名用于批量查询
+        List<String> userNameList = new ArrayList<>();
+        for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
+            Row row = sheet.getRow(rowIndex);
+            if (row == null || ExcelUtil.isRowEmpty(row)) {
+                continue;
+            }
+            
+            Cell nameCell = row.getCell(0);
+            if (nameCell == null) {
+                continue;
+            }
+            
+            String employeeName = nameCell.getStringCellValue().trim();
+            if (!employeeName.isEmpty() && !userNameList.contains(employeeName)) {
+                userNameList.add(employeeName);
+            }
+        }
+        
+        // 获取企业微信信息并批量查询用户
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
+
+        List<User> targetUserList = new ArrayList<>();
+        if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1 && userNameList.size() > 0) {
+            System.out.println("参与搜索的人员列表" + userNameList + " " + userNameList.size());
+            try {
+                HttpRespMsg respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, userNameList, null);
+                if (respMsg.code.equals("0")) {
+                    System.out.println("姓名为[" + String.valueOf(respMsg.data) + "]的人员存在重复,请使用工号!");
+                    return;
+                }
+                targetUserList = (List<User>) respMsg.data;
+            } catch (Exception e) {
+                System.out.println("批量查询用户信息失败: " + e.getMessage());
+                e.printStackTrace();
+            }
+        }
+        System.out.println("找到企业微信用户size="+targetUserList.size());
+        // 解析数据行
+        for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
+            Row row = sheet.getRow(rowIndex);
+            if (row == null || ExcelUtil.isRowEmpty(row)) {
+                continue;
+            }
+            
+            Cell nameCell = row.getCell(0);
+            if (nameCell == null) {
+                continue;
+            }
+            
+            String employeeName = nameCell.getStringCellValue().trim();
+            if (employeeName.isEmpty()) {
+                continue;
+            }
+            
+            // 查找对应的用户
+            User matchedUser = findUserByNameOrJobNumber(allUserList, employeeName, targetUserList, wxCorpInfo);
+            if (matchedUser == null) {
+                System.out.println("未找到用户: " + employeeName);
+                continue;
+            }
+            
+            // 解析每天的工时数据
+            for (int colIndex = 0; colIndex < dateColumns.size(); colIndex++) {
+                LocalDate workDate = dateColumns.get(colIndex);
+                if (workDate == null) {
+                    continue;
+                }
+                
+                Cell workHoursCell = row.getCell(colIndex + 2); // +2是因为前两列是姓名和部门
+                if (workHoursCell == null) {
+                    continue;
+                }
+                
+                Double workHours = parseWorkHours(workHoursCell);
+                if (workHours == null || workHours <= 0) {
+                    System.out.println("工时为空");
+                    continue;
+                }
+                
+                // 创建UserCorpwxTime对象
+                UserCorpwxTime corpwxTime = new UserCorpwxTime();
+                corpwxTime.setName(matchedUser.getName());
+                corpwxTime.setCorpwxUserid(matchedUser.getCorpwxUserid());
+                corpwxTime.setCreateDate(workDate);
+                corpwxTime.setWorkHours(workHours);
+                corpwxTime.setCompanyId(companyId);
+                corpwxTime.setWeekDay(workDate.getDayOfWeek().getValue());
+                corpwxTime.setWeekDayTxt(DateTimeUtil.getWeekDayTxt(corpwxTime.getWeekDay()));
+                
+                importedDataList.add(corpwxTime);
+            }
+        }
+    }
+    
+    /**
+     * 从Sheet名称中提取年月信息
+     */
+    private String extractYearMonth(String sheetName) {
+        // 处理类似 "1月", "2月" 等格式,默认为2025年
+        if (sheetName.matches("\\d+月")) {
+            int month = Integer.parseInt(sheetName.replace("月", ""));
+            return String.format("2025%02d", month);
+        }
+        
+        // 处理其他可能的格式
+        if (sheetName.matches("\\d{4}-\\d{1,2}")) {
+            String[] parts = sheetName.split("-");
+            return String.format("%s%02d", parts[0], Integer.parseInt(parts[1]));
+        }
+        
+        return null;
+    }
+    
+    /**
+     * 根据姓名或工号查找用户
+     */
+    private User findUserByNameOrJobNumber(List<User> allUserList, String nameOrJobNumber, 
+                                          List<User> targetUserList, WxCorpInfo wxCorpInfo) {
+        // 检查人员是否存在
+        Optional<User> any;
+        if ((wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1)) {
+            // 企业微信或钉钉模式,需要通过targetUserList进行匹配
+            Optional<User> optional = targetUserList.stream()
+                    .filter(tl -> tl.getName().equals(nameOrJobNumber))
+                    .findFirst();
+            any = allUserList.stream()
+                    .filter(u -> u.getName().equals(nameOrJobNumber) || 
+                                (u.getJobNumber() != null && u.getJobNumber().equals(nameOrJobNumber)) ||
+                                (optional.isPresent() && 
+                                 ((u.getCorpwxUserid() != null && u.getCorpwxUserid().equals(optional.get().getCorpwxUserid())) )))
+                    .findAny();
+        } else {
+            // 普通模式,直接按姓名或工号匹配
+            any = allUserList.stream()
+                    .filter(u -> u.getName().equals(nameOrJobNumber) || 
+                                (u.getJobNumber() != null && u.getJobNumber().equals(nameOrJobNumber)))
+                    .findAny();
+        }
+        
+        return any.orElse(null);
+    }
+    
+    /**
+     * 解析工时数据
+     */
+    private Double parseWorkHours(Cell cell) {
+        try {
+            if (cell.getCellTypeEnum() == CellType.NUMERIC) {
+                return cell.getNumericCellValue();
+            } else if (cell.getCellTypeEnum() == CellType.STRING) {
+                String value = cell.getStringCellValue().trim();
+                if (value.equals("×") || value.equals("√") || value.isEmpty()) {
+                    return null;
+                }
+                return Double.parseDouble(value);
+            }
+        } catch (Exception e) {
+            // 解析失败,返回null
+        }
+        return null;
+    }
+    
+    /**
+     * 比对和更新工时数据
+     */
+    private void compareAndUpdateWorktime(List<UserCorpwxTime> importedDataList, Integer companyId) {
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        
+        // 获取企业微信信息
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
+
+        // 获取所有用户名用于批量查询
+        List<String> allUserNames = importedDataList.stream()
+                .map(UserCorpwxTime::getName)
+                .distinct()
+                .collect(Collectors.toList());
+        
+        // 批量查询用户信息
+        List<User> targetUserList = new ArrayList<>();
+        if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1 && allUserNames.size() > 0) {
+            try {
+                HttpRespMsg respMsg = wxCorpInfoService.getBatchSearchUserInfo(wxCorpInfo, allUserNames, null);
+                if (!respMsg.code.equals("0")) {
+                    targetUserList = (List<User>) respMsg.data;
+                }
+            } catch (Exception e) {
+                System.out.println("批量查询用户信息失败: " + e.getMessage());
+                e.printStackTrace();
+            }
+        }
+
+        // 获取公司所有用户
+        List<User> allUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+        
+        // 按用户和日期分组
+        Map<String, List<UserCorpwxTime>> groupedData = importedDataList.stream()
+                .collect(Collectors.groupingBy(item -> item.getName() + "_" + item.getCreateDate().format(dtf)));
+        
+        for (Map.Entry<String, List<UserCorpwxTime>> entry : groupedData.entrySet()) {
+            List<UserCorpwxTime> dayDataList = entry.getValue();
+            if (dayDataList.isEmpty()) {
+                continue;
+            }
+            
+            UserCorpwxTime firstItem = dayDataList.get(0);
+            String userName = firstItem.getName();
+            LocalDate workDate = firstItem.getCreateDate();
+            Double importedWorkHours = dayDataList.stream().mapToDouble(UserCorpwxTime::getWorkHours).sum();
+            
+            // 通过企业微信搜索结果查找用户ID
+            User user = findUserByNameOrJobNumber(allUserList, userName, targetUserList, wxCorpInfo);
+            
+            if (user == null) {
+                System.out.println("未找到用户: " + userName);
+                continue;
+            }
+            
+            // 查询该用户当天在系统中填报的工时记录
+            List<Report> existingReports = reportService.list(new QueryWrapper<Report>()
+                    .eq("creator_id", user.getId())
+                    .eq("create_date", workDate)
+                    .eq("company_id", companyId));
+            
+            // 计算系统中已填报的总工时
+            Double systemWorkHours = existingReports.stream()
+                    .mapToDouble(report -> report.getWorkingTime() != null ? report.getWorkingTime() : 0.0)
+                    .sum();
+            
+            // 比对工时
+            if (Math.abs(importedWorkHours - systemWorkHours) > 0.01) { // 允许0.01的误差
+                System.out.println("=== 工时不一致,需要更新 ===");
+                System.out.println("用户: " + userName + " (" + user.getId() + ")");
+                System.out.println("日期: " + workDate.format(dtf));
+                System.out.println("导入工时: " + importedWorkHours);
+                System.out.println("系统工时: " + systemWorkHours);
+                
+                if (!existingReports.isEmpty()) {
+                    // 按比例分配新的工时
+                    updateReportWorktime(existingReports, importedWorkHours, systemWorkHours);
+                } else {
+                    System.out.println("该用户当天无填报记录,跳过更新");
+                }
+                
+                System.out.println("========================");
+            }
+        }
+    }
+    
+    /**
+     * 按比例更新报告工时
+     */
+    private void updateReportWorktime(List<Report> reports, Double newTotalWorkHours, Double oldTotalWorkHours) {
+        if (oldTotalWorkHours == 0) {
+            System.out.println("原工时为0,无法按比例分配");
+            return;
+        }
+        
+        for (Report report : reports) {
+            Double oldWorkTime = report.getWorkingTime() != null ? report.getWorkingTime() : 0.0;
+            Double ratio = oldWorkTime / oldTotalWorkHours;
+            Double newWorkTime = newTotalWorkHours * ratio;
+            
+            // 保留两位小数
+            newWorkTime = Math.round(newWorkTime * 100.0) / 100.0;
+            
+            System.out.println("项目ID: " + report.getProjectId() + 
+                             ", 原工时: " + oldWorkTime + 
+                             ", 新工时: " + newWorkTime + 
+                             ", 比例: " + String.format("%.2f%%", ratio * 100));
+            
+            // 更新工时
+            report.setWorkingTime(newWorkTime);
+//            reportService.updateById(report);
+        }
+    }
+}

+ 358 - 3
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/controller/PlanController.java

@@ -1,15 +1,19 @@
 package com.management.platform.controller;
 
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.management.platform.entity.*;
-import com.management.platform.service.PlanService;
-import com.management.platform.service.PlanSteelStampNumberService;
-import com.management.platform.service.ReportService;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.*;
+import com.management.platform.util.DateTimeUtil;
 import com.management.platform.util.HttpRespMsg;
 import org.apache.ibatis.annotations.Param;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 
@@ -19,7 +23,14 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 /**
  * <p>
@@ -39,6 +50,18 @@ public class PlanController {
     private PlanSteelStampNumberService planSteelStampNumberService;
     @Resource
     private ReportService reportService;
+    @Resource
+    private PlanExtraInfoService extraInfoService;
+    @Resource
+    WxCorpTemplateService wxCorpTemplateService;
+    @Resource
+    private WxCorpInfoService wxCorpInfoService;
+    @Resource
+    TaskTypeService taskTypeService;
+    @Resource
+    UserMapper userMapper;
+    @Resource
+    DepartmentService departmentService;
 
     @RequestMapping("/list")
     public HttpRespMsg list(String date,String steelStampNumber,@RequestParam(defaultValue = "3") Integer planType,Integer deptId,Integer pageIndex,Integer pageSize,Integer isMob,Integer searchType,String searchValue){
@@ -219,5 +242,337 @@ public class PlanController {
     public HttpRespMsg updateHasDeleteTeamData(){
         return reportService.updateHasDeleteTeamData();
     }
+
+    @RequestMapping("/getTemporaryJobApplicationNew")
+    public HttpRespMsg getTemporaryJobApplicationNew(String startDate, String endDate) throws Exception {
+        HttpRespMsg httpRespMsg=new HttpRespMsg();
+        JSONArray jsonArrayFilter = new JSONArray();
+        JSONObject filter1 = new JSONObject();
+        WxCorpTemplate template = wxCorpTemplateService.getOne(new QueryWrapper<WxCorpTemplate>().eq("company_id",7).eq("type",2));//类型设置为2
+        filter1.put("key","template_id");
+        filter1.put("value",template.getTemplateId());
+        jsonArrayFilter.add(filter1);
+        JSONObject filter2 = new JSONObject();
+        filter2.put("key","sp_status");
+        filter2.put("value","2");
+        jsonArrayFilter.add(filter2);
+        System.out.println("开始获取getTemporaryJobApplicationNew==计件工单数据==!!");
+        List<String> approvalInfo = wxCorpInfoService.getApprovalInfo(7, startDate, endDate, "", jsonArrayFilter);
+        List<Department> departmentList = departmentService.list(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, 7));
+        List<TaskType> taskTypeList = taskTypeService.list(new LambdaQueryWrapper<TaskType>().eq(TaskType::getCompanyId, 7));
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId,7));
+        if(approvalInfo!=null){
+            System.out.println("计件工单数据="+approvalInfo.size()+"条");
+            for (int i = 0; i < approvalInfo.size(); i++) {
+                String codeNum = approvalInfo.get(i);
+                String approvalInfoDetailResp = wxCorpInfoService.getApprovalInfoDetail(7, codeNum);
+                JSONObject approvalInfoDetail = JSONObject.parseObject(approvalInfoDetailResp);
+                JSONObject info = approvalInfoDetail.getJSONObject("info");
+                JSONObject applyer = info.getJSONObject("applyer");
+                String userid = applyer.getString("userid");
+                //过滤审核状态只需要审核通过的数据
+                int sp_status = info.getIntValue("sp_status");
+                if(sp_status!=2){
+                    continue;
+                }
+                Optional<User> first = userList.stream().filter(u ->u.getCorpwxRealUserid()!=null&&u.getCorpwxRealUserid().equals(userid)).findFirst();
+                if(!first.isPresent()){
+                    continue;
+                }
+                JSONObject apply_data = info.getJSONObject("apply_data");
+                System.out.println("获取到的单据信息===========>"+apply_data);
+                JSONArray contents = apply_data.getJSONArray("contents");
+                //生成 车间插单计划
+                List<Plan> planList = planService.list(new LambdaQueryWrapper<Plan>().eq(Plan::getTaskChangeNoticeNum, info.getString("sp_no")));
+                Plan plan=new Plan();
+                if(!planList.isEmpty()){
+                    plan.setId(planList.get(0).getId());
+                }
+                plan.setCompanyId(7);
+                plan.setCreateTime(LocalDateTime.now());
+                plan.setPlanType(1);
+                plan.setCreateId(first.get().getId());
+                plan.setTaskChangeNoticeNum(info.getString("sp_no"));
+                //参与人员列表
+                List<String> userTeams=new ArrayList<>();
+                //初始化 单价(元/小时)
+                BigDecimal price=new BigDecimal(0);
+                //初始化 工作时长
+                double workTime=0;
+
+                long apply_time = info.getLongValue("apply_time");
+                LocalDate createDate;
+                if(apply_time>0){
+                    createDate=  DateTimeUtil.getLocalDateFromUnix(apply_time);
+                }else {
+                    createDate  =LocalDate.now();
+                }
+                //初始化工位
+                Integer deptId=0;
+                long startTime=0;
+                long endTime=0;
+                String steelNumArray="";
+                String operationName="";
+                String partName="";
+                for (int i1 = 0; i1 < contents.size(); i1++) {
+                    JSONObject map = contents.getJSONObject(i1);
+                    JSONArray title = map.getJSONArray("title");
+                    JSONObject value = map.getJSONObject("value");
+                    String control = map.getString("control");
+                    /*if(title.getJSONObject(0).getString("text").equals("临时报工分类")){
+                        if(control.equals("Selector")){
+                            JSONObject selector = value.getJSONObject("selector");
+                            JSONArray options = selector.getJSONArray("options");
+                            JSONObject object = options.getJSONObject(0);
+                            JSONArray value1 = object.getJSONArray("value");
+                            JSONObject jsonObject = value1.getJSONObject(0);
+                            String text = jsonObject.getString("text");
+                            Optional<TaskType> first1 = taskTypeList.stream().filter(t -> t.getTaskTypeName().equals(text)).findFirst();
+                            if(first1.isPresent()){
+                                plan.setTaskTypeId(first1.get().getId());
+                                plan.setTaskTypeName(first1.get().getTaskTypeName());
+                            }
+                        }
+                    }*/
+                    if(title.getJSONObject(0).getString("text").equals("项目名称")){
+                        if(control.equals("Text")||control.equals("Textarea")){
+                            String text = value.getString("text");
+                            plan.setProjectName(text);
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").contains("包名称")){
+                        if(control.equals("Text")||control.equals("Textarea")){
+                            String text = value.getString("text");
+                            plan.setProductSchedulingNum(text);
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("生产订单号")){
+                        if(control.equals("Text")||control.equals("Textarea")){
+                            String text = value.getString("text");
+                            plan.setProductOrderNum(text);
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("工序名称")){
+                        if(control.equals("Text")||control.equals("Textarea")){
+                            String text = value.getString("text");
+                            operationName=text;//工序名称
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("零件编码")){
+                        if(control.equals("Text")||control.equals("Textarea")){
+                            String text = value.getString("text");
+                            steelNumArray=text;//零件编码
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("零件名称")){
+                        if(control.equals("Text")||control.equals("Textarea")){
+                            String text = value.getString("text");
+                            partName=text;//零件名称
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("生产数量")){
+                        if(control.equals("Number")){
+                            int new_number= value.get("new_number")!=null?value.getIntValue("new_number"):0;
+                            plan.setNum(new_number);
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("作业单位")){
+                        if(control.equals("Contact")){
+                            JSONArray departments = value.getJSONArray("departments");
+                            String openapi_id = departments.getJSONObject(0).getString("openapi_id");
+                            Optional<Department> first1 = departmentList.stream().filter(d -> d.getCorpwxDeptid().equals(Integer.valueOf(openapi_id))).findFirst();
+                            if(first1.isPresent()){
+                                plan.setStationId(first1.get().getDepartmentId());
+                                plan.setStationName(first1.get().getDepartmentName());
+                                plan.setForemanId(first1.get().getManagerId());
+                                Optional<User> first2 = userList.stream().filter(u -> u.getId().equals(first1.get().getManagerId())).findFirst();
+                                if(first2.isPresent()){
+                                    plan.setForemanName(first2.get().getName());
+                                }
+                                deptId=first1.get().getDepartmentId();
+                            }
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").contains("单价")){
+                        if(control.equals("Number")){
+                            if(!value.getString("new_number").equals("")){
+                                Double new_money = value.getDouble("new_number");
+                                plan.setMoneyOfJob(new BigDecimal(new_money==null?0:new_money));
+                                price=new BigDecimal(new_money);
+                            }
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").contains("结算总额")){
+                        if(control.equals("Formula")){
+                            JSONObject formula = value.getJSONObject("formula");
+                            if(!formula.getString("value").equals("")){
+                                double formulaDoubleValue = formula.getDoubleValue("value");
+                                BigDecimal bigDecimal = new BigDecimal(formulaDoubleValue);
+                                if(workTime>0){
+                                    BigDecimal divide = bigDecimal.divide(new BigDecimal(workTime), 3, RoundingMode.HALF_UP);
+                                    plan.setMoneyOfJob(divide);
+                                }
+                                plan.setSettlementAmount(bigDecimal);
+                            }
+                        }
+                    }
+                    //先处理多个人员 公用此单据非工时部分内容
+                    if(title.getJSONObject(0).getString("text").equals("作业人员")){
+                        if(control.equals("Contact")){
+                            JSONArray members = value.getJSONArray("members");
+                            plan.setPlanManNum(members.size());
+                            for (int i2 = 0; i2 < members.size(); i2++) {
+                                JSONObject jsonObject = members.getJSONObject(i2);
+                                String userid1 = jsonObject.getString("userid");
+                                userTeams.add(userid1);
+                            }
+
+                        }
+                    }
+
+
+                    if(title.getJSONObject(0).getString("text").equals("作业开始日期")){
+                        if(control.equals("Date")){
+                            JSONObject date = value.getJSONObject("date");
+                            long s_timestamp = date.getLongValue("s_timestamp");
+                            startTime=s_timestamp;
+                            LocalDate localDateFromUnix = DateTimeUtil.getLocalDateFromUnix(s_timestamp);
+                            plan.setStartDate(localDateFromUnix);
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("作业结束日期")){
+                        if(control.equals("Date")){
+                            long s_timestamp=0;
+                            JSONObject date = value.getJSONObject("date");
+                            if (!StringUtils.isEmpty(date.getString("s_timestamp"))){
+                                s_timestamp= date.getLongValue("s_timestamp");
+                                LocalDate localDateFromUnix = DateTimeUtil.getLocalDateFromUnix(s_timestamp);
+                                plan.setEndDate(localDateFromUnix);
+                            }
+                            if (s_timestamp!=0){
+                                endTime=s_timestamp;
+                            }
+                        }
+                    }
+                    if (endTime>0){
+                        long l = endTime - startTime;//工作时长
+                        workTime=l/3600.0;
+                        plan.setPlanWorkHour(workTime);//小时
+
+                        startTime=0;
+                        endTime=0;
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("所属工位长")){
+                        if(control.equals("Contact")){
+                            JSONArray members = value.getJSONArray("members");
+                            String userid2 = members.getJSONObject(0).getString("userid");
+                            User user = userMapper.selectOne(new QueryWrapper<User>().eq("corpwx_real_userid", userid2));
+                            Department department = departmentService.getById(user.getDepartmentId());
+                            if (user != null) {
+                                plan.setForemanId(user.getId());
+                                plan.setForemanName(user.getName());
+                                if (department != null) {
+                                    plan.setStationId(department.getDepartmentId());
+                                    plan.setStationName(department.getDepartmentName());
+                                }
+                            }
+                        }
+                    }
+                    if(title.getJSONObject(0).getString("text").equals("备注")){
+                        if(control.equals("Text")||control.equals("Textarea")){
+                            String text = value.getString("text");
+                            plan.setDescribtion(text);
+                        }
+                    }
+                }
+                if (plan.getId()!=null){
+                    planService.update(new UpdateWrapper<Plan>().eq("id", plan.getId()).set("money_of_job",plan.getMoneyOfJob()));
+                    int count = reportService.count(new QueryWrapper<Report>().eq("plan_id", plan.getId()));
+                    if (count!=userTeams.size()){
+//                        log.info("userTeams的长度:"+userTeams.size());
+//                        log.info("userTeams的内容:"+(userTeams.isEmpty() ?"":userTeams.toString()));
+//                        log.info("plan.getSettlementAmount():"+plan.getSettlementAmount());
+                        reportService.remove(new QueryWrapper<Report>().eq("plan_id", plan.getId()));
+                        List<Report> reportList = new ArrayList<>();
+                        List<PlanExtraInfo> planExtraInfoList = new ArrayList<>();
+
+                        //处理人员日报数据
+                        for (String userTeam : userTeams) {
+                            Optional<User> user = userList.stream().filter(u -> u.getCorpwxRealUserid() != null && u.getCorpwxRealUserid().equals(userTeam)).findFirst();
+                            if (user.isPresent()) {
+                                Report report = new Report();
+                                report.setCreateDate(createDate);
+                                report.setCreatorId(user.get().getId());
+                                report.setCreateTime(LocalDateTime.now());
+                                BigDecimal bigDecimal = new BigDecimal(workTime);
+                                report.setWorkingTime(bigDecimal.doubleValue());
+                                report.setCost(plan.getSettlementAmount().divide(BigDecimal.valueOf(userTeams.size()), 2, RoundingMode.HALF_UP));
+                                report.setStatus(2);
+                                report.setPlanId(plan.getId());
+                                report.setCompanyId(7);
+                                report.setDeptId(user.get().getDepartmentId());
+                                report.setSteelNumArray(steelNumArray);
+                                reportList.add(report);
+                            }
+                        }
+                        if (reportList.size() > 0) {
+                            reportService.saveBatch(reportList);
+                            for (Report report : reportList) {
+                                PlanExtraInfo planExtraInfo = new PlanExtraInfo();
+                                planExtraInfo.setPlanId(plan.getId());
+                                planExtraInfo.setReportId(report.getId());
+                                planExtraInfo.setOperationName(operationName);
+                                planExtraInfo.setPartName(partName);
+                                planExtraInfoList.add(planExtraInfo);
+                            }
+                            if (planExtraInfoList.size() > 0) {
+                                extraInfoService.saveBatch(planExtraInfoList);
+                            }
+                        }
+                    }
+                }else {
+                    planService.save(plan);
+                    List<Report> reportList = new ArrayList<>();
+                    List<PlanExtraInfo> planExtraInfoList = new ArrayList<>();
+
+                    //处理人员日报数据
+                    for (String userTeam : userTeams) {
+                        Optional<User> user = userList.stream().filter(u -> u.getCorpwxRealUserid() != null && u.getCorpwxRealUserid().equals(userTeam)).findFirst();
+                        if (user.isPresent()) {
+                            Report report = new Report();
+                            report.setCreateDate(createDate);
+                            report.setCreatorId(user.get().getId());
+                            report.setCreateTime(LocalDateTime.now());
+                            BigDecimal bigDecimal = new BigDecimal(workTime);
+                            report.setWorkingTime(bigDecimal.doubleValue());
+                            report.setCost(plan.getSettlementAmount().divide(BigDecimal.valueOf(userTeams.size()), 2, RoundingMode.HALF_UP));
+                            report.setStatus(2);
+                            report.setPlanId(plan.getId());
+                            report.setCompanyId(7);
+                            report.setDeptId(user.get().getDepartmentId());
+                            report.setSteelNumArray(steelNumArray);
+                            reportList.add(report);
+                        }
+                    }
+                    if (reportList.size() > 0) {
+                        reportService.saveBatch(reportList);
+                        for (Report report : reportList) {
+                            PlanExtraInfo planExtraInfo = new PlanExtraInfo();
+                            planExtraInfo.setPlanId(plan.getId());
+                            planExtraInfo.setReportId(report.getId());
+                            planExtraInfo.setOperationName(operationName);
+                            planExtraInfo.setPartName(partName);
+                            planExtraInfoList.add(planExtraInfo);
+                        }
+                        if (planExtraInfoList.size() > 0) {
+                            extraInfoService.saveBatch(planExtraInfoList);
+                        }
+                    }
+                }
+            }
+        }
+
+        return httpRespMsg;
+    }
 }
 

+ 4 - 4
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/service/impl/PlanServiceImpl.java

@@ -1729,10 +1729,11 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
     public HttpRespMsg allocationUser(Integer planId) {
         HttpRespMsg msg=new HttpRespMsg();
         Plan plan = planMapper.selectById(planId);
-        List<Plan> plans = planMapper.selectList(new LambdaQueryWrapper<Plan>().eq(Plan::getStationId, plan.getStationId()).ne(Plan::getId,plan.getId()).eq(Plan::getProductId, plan.getProductId()).orderByDesc(Plan::getCreateTime));
+        //查找早于当前这个计划创建的计划,工位&产品一致的最新记录。
+        Plan oldPlan = planMapper.selectOne(new LambdaQueryWrapper<Plan>().eq(Plan::getStationId, plan.getStationId()).ne(Plan::getId,plan.getId())
+                .eq(Plan::getProductId, plan.getProductId()).lt(Plan::getCreateTime,plan.getCreateTime()).orderByDesc(Plan::getCreateTime).last("LIMIT 1"));
         List<PlanProcedureTotal> planProcedureTotals = planProcedureTotalService.list(new LambdaQueryWrapper<PlanProcedureTotal>().eq(PlanProcedureTotal::getPlanId, plan.getId()));
-        if(plans.size()>0){
-            Plan oldPlan = plans.get(0);
+        if(oldPlan != null) {
             List<PlanProcedureTotal> oldTotalList = planProcedureTotalService.list(new LambdaQueryWrapper<PlanProcedureTotal>().eq(PlanProcedureTotal::getPlanId, oldPlan.getId()));
             List<Integer> ids = oldTotalList.stream().map(PlanProcedureTotal::getId).distinct().collect(Collectors.toList());
             ids.add(-1);
@@ -1752,7 +1753,6 @@ public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements Pl
                     }
                 }
             }
-
         }
         return msg;
     }

+ 3 - 1
fhKeeper/formulahousekeeper/management-workshop/src/main/java/com/management/platform/task/TimingTask.java

@@ -585,12 +585,13 @@ public class TimingTask {
 
 
     @Scheduled(cron = "0 40 2 ? * *")
+//    @Scheduled(cron = "0 55 14 ? * *")
     public void getTemporaryJobApplicationNew() throws Exception {
         if(isDev){
             return;
         }
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        LocalDate start=LocalDate.now().minusDays(30);
+        LocalDate start= LocalDate.now().minusDays(30);
         LocalDate end=LocalDate.now();
         JSONArray jsonArrayFilter = new JSONArray();
         JSONObject filter1 = new JSONObject();
@@ -602,6 +603,7 @@ public class TimingTask {
         filter2.put("key","sp_status");
         filter2.put("value","2");
         jsonArrayFilter.add(filter2);
+        System.out.println("开始获取getTemporaryJobApplicationNew==计件工单数据==!!");
         List<String> approvalInfo = wxCorpInfoService.getApprovalInfo(7, df.format(start), df.format(end), "", jsonArrayFilter);
         List<Department> departmentList = departmentService.list(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, 7));
         List<TaskType> taskTypeList = taskTypeService.list(new LambdaQueryWrapper<TaskType>().eq(TaskType::getCompanyId, 7));

+ 223 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue

@@ -530,6 +530,12 @@
             <el-button size="small" type="primary" @click="holidaySeeting()">{{ $t('setup') }}</el-button>
             <span style="margin-left:10px;color:#999;">{{'设置部门或人员的特殊节假日'}}</span>
         </div>
+        <!-- 特殊人员填报设置 -->
+        <div class="yanjiu">
+            <p style="margin: 0 68px 0 10px;color:#666;">{{'特殊人员填报设置'}}</p>
+            <el-button size="small" type="primary" @click="specialPersonnelReportSetting()">{{ $t('setup') }}</el-button>
+            <span style="margin-left:10px;color:#999;">此配置用于对请假全天的情况下开放填写日报的权限</span>
+        </div>
         <!-- 屏蔽词设置 -->
         <div class="yanjiu" v-if="user.companyId == 1071">
             <p style="margin: 0 68px 0 10px;color:#666;">{{'屏蔽词设置'}}</p>
@@ -865,6 +871,64 @@
             </div>
         </el-dialog>
 
+        <!-- 特殊人员填报设置列表 -->
+        <el-dialog title="特殊人员填报设置列表" show-header="false" :top="'10vh'" v-if="specialPersonnelReportDialog" :visible.sync="specialPersonnelReportDialog" :close-on-click-modal="false" customClass="customWidth" width="800px">
+            <el-table :data="specialPersonnelReportDatas" highlight-current-row height="400" style="width: 100%;">
+                <el-table-column prop="date"  label="日期">
+                </el-table-column>
+                <el-table-column prop="userName" label="人员" >
+                    <template slot-scope="scope">
+                        <span v-if="user.userNameNeedTranslate != '1'">{{scope.row.userName}}</span>
+                        <span v-if="user.userNameNeedTranslate == '1'"><TranslationOpenDataText type='userName' :openid='scope.row.userName'></TranslationOpenDataText></span>
+                    </template>
+                </el-table-column>
+                <el-table-column :label="$t('operation')"  >
+                    <template slot-scope="scope">
+                        <el-button size="small" type="primary" @click="addNewSpecialPersonnelReport(scope.row)">{{ $t('bian-ji') }}</el-button>
+                        <el-button size="small" type="danger" @click="deleteSpecialPersonnelReport(scope.row)">{{ $t('btn.delete') }}</el-button>
+                    </template>
+                </el-table-column>
+            </el-table>
+            <div slot="footer" class="dialog-footer">
+                <el-button type="primary" @click="specialPersonnelReportDialog = false">{{ $t('Shutdown') }}</el-button>
+                <el-button type="primary" @click="addNewSpecialPersonnelReport()">{{ $t('addData') }}</el-button>
+            </div>
+        </el-dialog>
+
+        <!-- 新增特殊人员填报设置 -->
+        <el-dialog title="特殊人员填报设置" show-header="false" v-if="addSpecialPersonnelReport" :visible.sync="addSpecialPersonnelReport" :top="'10vh'" :close-on-click-modal="false" customClass="customWidth" width="600px">
+            <el-form ref="specialPersonnelReportForm" :model="specialPersonnelReportForm" label-width="80px">
+                <el-form-item label="日期" prop="date">
+                    <el-date-picker v-model="specialPersonnelReportForm.date"
+                        :editable="false"
+                        format="yyyy-MM-dd" 
+                        value-format="yyyy-MM-dd"
+                        :clearable="false" 
+                        type="date" 
+                        placeholder="请选择日期">
+                    </el-date-picker>
+                </el-form-item>
+                <el-form-item label="人员" prop="userId">
+                    <el-select v-model="specialPersonnelReportForm.userId" 
+                        placeholder="请选择人员" 
+                        filterable 
+                        style="width: 100%;">
+                        <el-option v-for="item in allUsersList" 
+                            :key="item.id" 
+                            :label="item.name" 
+                            :value="item.id">
+                            <span style="float: left">{{ item.name }}</span>
+                            <span style="float: right; color: #8492a6; font-size: 13px;margin-left: 20px" v-if="item.jobNumber">{{ item.jobNumber }}</span>
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button type="primary" @click="addSpecialPersonnelReport = false">{{ $t('Shutdown') }}</el-button>
+                <el-button type="primary" @click="submitInsertSpecialPersonnelReport()">{{ $t('save') }}</el-button>
+            </div>
+        </el-dialog>
+
         <!-- 特殊节假日设置 -->
         <el-dialog :title="specialHolidays == 1 ? $t('qing-xuan-ze-bu-men') : $t('pleaseselectpersonnel')" :top="'10vh'"  v-if="specialHolidaysDialog" :visible.sync="specialHolidaysDialog" :close-on-click-modal="false" customClass="customWidth" width="600px">
             <!-- 只有在非屏蔽词设置时才显示搜索功能 -->
@@ -1104,6 +1168,17 @@
                     labels: []
                 },
                 isMaskWordDialog: false, // 标识是否为屏蔽词对话框
+                
+                // 特殊人员填报设置相关数据
+                specialPersonnelReportDialog: false,
+                addSpecialPersonnelReport: false,
+                specialPersonnelReportForm: {
+                    date: '',
+                    userId: null,
+                    userName: ''
+                },
+                specialPersonnelReportDatas: [],
+                allUsersList: [], // 所有用户列表
             };
         },
         watch: {
@@ -1144,6 +1219,8 @@
             if(this.user.companyId == 4811) {
                 this.getMechanicalPersonnelList()
             }
+            // 初始化用户列表用于特殊人员填报设置
+            this.getAllUsersList()
         },
          methods: {
             startSynchronizing() {
@@ -2496,6 +2573,152 @@
                 this.$refs.specialHolidaysTree.setCheckedKeys(key)
             },
 
+            // 特殊人员填报设置相关方法
+            // 打开特殊人员填报设置列表
+            specialPersonnelReportSetting() {
+                this.specialPersonnelReportDialog = true
+                this.getSpecialPersonnelReportList()
+            },
+
+            // 获取特殊人员填报设置列表
+            getSpecialPersonnelReportList() {
+                this.http.post('/user-date-allow/list', {}, res => {
+                    if(res.code == 'ok') {
+                        this.specialPersonnelReportDatas = res.data || []
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        })
+                    }
+                }, err => {
+                    this.$message({
+                        message: err,
+                        type: 'error'
+                    })
+                })
+            },
+
+            // 新增/编辑特殊人员填报设置
+            addNewSpecialPersonnelReport(item) {
+                if(item) {
+                    this.specialPersonnelReportForm.date = item.date
+                    this.specialPersonnelReportForm.userId = item.userId
+                    this.specialPersonnelReportForm.userName = item.userName
+                    this.specialPersonnelReportForm.id = item.id
+                } else {
+                    this.specialPersonnelReportForm.date = ""
+                    this.specialPersonnelReportForm.userId = null
+                    this.specialPersonnelReportForm.userName = ""
+                    this.specialPersonnelReportForm.id = null
+                }
+                this.getAllUsersList()
+                this.addSpecialPersonnelReport = true
+            },
+
+            // 获取所有用户列表
+            getAllUsersList() {
+                this.http.post('/user/getSimpleActiveUserList', {}, res => {
+                    if(res.code == 'ok') {
+                        this.allUsersList = res.data || []
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        })
+                    }
+                }, err => {
+                    this.$message({
+                        message: err,
+                        type: 'error'
+                    })
+                })
+            },
+
+            // 提交特殊人员填报设置
+            submitInsertSpecialPersonnelReport() {
+                if(!this.specialPersonnelReportForm.date) {
+                    this.$message({
+                        message: '请选择日期',
+                        type: 'error'
+                    })
+                    return
+                }
+                if(!this.specialPersonnelReportForm.userId) {
+                    this.$message({
+                        message: '请选择人员',
+                        type: 'error'
+                    })
+                    return
+                }
+
+                // 获取选中人员的姓名
+                const selectedUser = this.allUsersList.find(user => user.id === this.specialPersonnelReportForm.userId)
+                if(selectedUser) {
+                    this.specialPersonnelReportForm.personnelName = selectedUser.name
+                }
+
+                let newForm = {
+                    ...this.specialPersonnelReportForm
+                }
+                this.http.post('/user-date-allow/userDateAllow', {...newForm}, res => {
+                    if(res.code == 'ok') {
+                        this.$message({
+                            message: this.$t('savesuccess'),
+                            type: 'success'
+                        })
+                        this.addSpecialPersonnelReport = false
+                        this.getSpecialPersonnelReportList()
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        })
+                    }
+                }, err => {
+                    this.$message({
+                        message: err,
+                        type: 'error'
+                    })
+                })
+            },
+
+            // 删除特殊人员填报设置
+            deleteSpecialPersonnelReport(item) {
+                this.$confirm('确定删除这条数据吗?', '删除', {
+                    confirmButtonText: this.$t('btn.determine'),
+                    cancelButtonText: this.$t('btn.cancel'),
+                    type: "warning"
+                })
+                .then(() => {
+                    this.listLoading = true;
+                    this.http.post('/user-date-allow/delete', { 
+                        id: item.id 
+                    }, res => {
+                        this.listLoading = false;
+                        if (res.code == "ok") {
+                            this.$message({
+                                message: this.$t('message.successfullyDeleted'),
+                                type: "success"
+                            });
+                            this.getSpecialPersonnelReportList();
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                    }, error => {
+                        this.listLoading = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+                })
+                .catch(() => {});
+            },
+
         },
     };
 </script>