Ver Fonte

增加请假接口,增加任务类型:BUG

QuYueTing há 1 semana atrás
pai
commit
2c692e9117
25 ficheiros alterados com 479 adições e 39 exclusões
  1. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java
  2. 11 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/LeaveSheetController.java
  3. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  4. 9 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  5. 61 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserCorpwxTimeController.java
  6. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/CompanyDingdingService.java
  7. 10 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java
  8. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  9. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/CompanyDingdingServiceImpl.java
  10. 110 12
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  11. 37 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  12. 1 1
      fhKeeper/formulahousekeeper/timesheet-workshop/config/index.js
  13. 141 3
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/demo_index.html
  14. 27 3
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.css
  15. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.js
  16. 42 0
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.json
  17. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.ttf
  18. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.woff
  19. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.woff2
  20. 3 3
      fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue
  21. 2 2
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  22. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/gantt.vue
  23. 3 3
      fhKeeper/formulahousekeeper/timesheet/src/views/project/projectInside.vue
  24. 1 0
      fhKeeper/formulahousekeeper/timesheet/src/views/task/list.vue
  25. 2 1
      fhKeeper/formulahousekeeper/timesheet_mld/src/components/taskComponent.vue

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java

@@ -351,4 +351,10 @@ public class DingDingController {
         return dingDingService.initSuperManager(corpid, name);
     }
 
+    @RequestMapping("/getAttendanceScheduleResult")
+    public HttpRespMsg getAttendanceScheduleResult(Integer companyId, String userId, String date) {
+        User user = userMapper.selectById(userId);
+        return dingDingService.getAttendanceScheduleResult(companyId, user.getDingdingUserid(), date, date);
+    }
+
 }

+ 11 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/LeaveSheetController.java

@@ -81,6 +81,17 @@ public class LeaveSheetController {
 
     }
 
+    @RequestMapping("/addLeaveSheet")
+    public HttpRespMsg addLeaveSheet(LeaveSheet sheet) {
+        if (sheet.getOwnerId() == null) {
+
+        }
+        leaveSheetService.save(sheet);
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        httpRespMsg.setData(sheet);
+        return httpRespMsg;
+    }
+
     @RequestMapping("/cancel")
     public HttpRespMsg cancel(Integer id) {
         String userId = request.getHeader("Token");

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

@@ -138,6 +138,10 @@ public class ProjectController {
         return projectMainService.getAllMainProject(request);
     }
 
+    @RequestMapping("/getRemainingTime")
+    public HttpRespMsg getRemainingTime(Integer projectId) {
+        return projectService.getRemainingTime(projectId, request);
+    }
 
     /**
      * 预估工时表

+ 9 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.pagehelper.util.StringUtil;
 import com.management.platform.config.LimitRequest;
+import com.management.platform.config.NewLimitRequest;
 import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.MonthWorkingTimeVO;
@@ -18,6 +19,7 @@ import com.management.platform.service.*;
 import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import com.management.platform.util.*;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.*;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.client.RestTemplate;
@@ -2874,6 +2876,13 @@ public class ReportController {
     @LimitRequest(count = 10)
     @PostMapping("/getReportListByToken")
     public HttpRespMsg getReportListByToken(@RequestBody String json){
+        HttpRespMsg httpRespMsg = reportService.getReportListByToken(json);
+        return httpRespMsg;
+    }
+
+    @NewLimitRequest(count = 10)
+    @PostMapping("/getReportListByTokenNew")
+    public HttpRespMsg getReportListByTokenNew(@RequestBody String json){
         return reportService.getReportListByToken(json);
     }
 

+ 61 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserCorpwxTimeController.java

@@ -1786,9 +1786,66 @@ public class UserCorpwxTimeController {
             Sheet staffSheet = workbook.getSheetAt(1);
             System.out.println("正在处理第二个Sheet: " + staffSheet.getSheetName() + " (人员分配)");
             List<Map<String, Object>> staffAllocationResult = processStaffAllocationSheet(staffSheet, companyId, allUserList);
-            
+            //检查系统中是否存在表格中员工没有参与的项目
+            List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", companyId));
+            List<Participation> participationList = participationMapper.selectList(new QueryWrapper<Participation>().in("project_id", projectList.stream().map(Project::getId).collect(Collectors.toList())));
+
+            List<HashMap> shouldDeleteParticipation = new ArrayList<>();
+            for (Participation participation : participationList) {
+                Project p = projectList.stream().filter(ppo->ppo.getId().equals(participation.getProjectId())).findFirst().get();
+                //如果是项目经理,跳过检查
+                if (p.getInchargerId() != null && p.getInchargerId().equals(participation.getUserId())) {
+                    continue;
+                }
+                //检查是否存在
+                boolean find = false;
+                boolean findProjectInTable = false;
+                //检查项目是否在当前的表格中
+                for (Map<String, Object> map : staffAllocationResult) {
+                    Integer projectId = (Integer)map.get("projectId");
+                    if (projectId.equals(participation.getProjectId())) {
+                        findProjectInTable = true;
+                        break;
+                    }
+                }
+                //参与的项目不在当前表格中,跳过
+                if (!findProjectInTable) {
+                    continue;
+                }
+                for (Map<String, Object> map : staffAllocationResult) {
+                    Integer projectId = (Integer)map.get("projectId");
+                    String employeeId = (String)map.get("employeeId");
+                    if (projectId.equals(participation.getProjectId()) && employeeId.equals(participation.getUserId())) {
+                        find = true;
+                        break;
+                    }
+                }
+                if (!find) {
+                    HashMap map = new HashMap();
+                    map.put("id", participation.getId());
+                    map.put("projectId", participation.getProjectId());
+
+                    map.put("projectCode", p.getProjectCode());
+                    map.put("projectName", p.getProjectName());
+                    map.put("userId", participation.getUserId());
+                    User findUser = allUserList.stream().filter(u->u.getId().equals(participation.getUserId())).findFirst().get();
+                    map.put("userName", findUser.getName());
+                    map.put("jobNumber", findUser.getJobNumber());
+                    shouldDeleteParticipation.add(map);
+                }
+            }
+//                    msg.setError("员工 " + participation.getUserId() + " 没有参与项目 code =" + participation.getProjectId() + projectList.stream().filter(p->p.getId().equals(participation.getProjectId())).findFirst().get().getProjectCode() + ", name=" +
+//                            projectList.stream().filter(p->p.getId().equals(participation.getProjectId())).findFirst().get().getProjectName());
+//                    return msg;
             // 返回员工-项目-可填月份的数据集合
+//            HashMap retMap = new HashMap();
+//            retMap.put("data", staffAllocationResult);
+//            retMap.put("shouldDeleteParticipation", shouldDeleteParticipation);
             msg.data = staffAllocationResult;
+//            if (shouldDeleteParticipation.size() > 0) {
+//                //删除数据
+//                participationMapper.deleteBatchIds(shouldDeleteParticipation.stream().map(map->(Integer)map.get("id")).collect(Collectors.toList()));
+//            }
             System.out.println("项目和人员分配数据导入完成,共处理 " + staffAllocationResult.size() + " 条员工分配记录");
             IMPORTED_SHEET_ONE_DATA = staffAllocationResult;
         } catch (IOException e) {
@@ -2123,7 +2180,7 @@ public class UserCorpwxTimeController {
         LocalDate startMonth = now.withDayOfMonth(1).withMonth(1);
 
         if (headerRow != null) {
-            for (int colIndex = 11; colIndex < 11 + 12; colIndex++) { // 第12列开始(索引11)
+            for (int colIndex = 11; colIndex < 11 + 24; colIndex++) { // 第12列开始(索引11)
                 Cell cell = headerRow.getCell(colIndex);
                 if (cell != null) {
                     String monthStr = startMonth.plusMonths(colIndex - 11).format(DateTimeFormatter.ofPattern("yyyy-MM"));
@@ -2202,10 +2259,10 @@ public class UserCorpwxTimeController {
                     currentEmployee[0] = allUserList.stream().filter(u -> u.getJobNumber() != null && u.getJobNumber().equals(finalJobNumber)).findFirst().orElse(null);
                     if (currentEmployee[0] == null) {
                         // 查找员工 - 使用企业微信搜索结果进行匹配
-                        System.out.println("未找到员工姓名为 " + currentEmployeeName[0] + " 的员工,使用企业微信搜索");
+                        System.out.println("未找到员工工号为 " + finalJobNumber + " 的员工,使用企业微信搜索");
                         currentEmployee[0] = findUserByNameWithWxSearch(allUserList, currentEmployeeName[0], targetUserList, wxCorpInfo, null);
                         if (currentEmployee[0] == null) {
-                            System.out.println("未找到员工工号为 " + currentJobNumber[0] + " 的员工");
+                            System.out.println("未找到员工姓名为 " + currentEmployeeName[0] + " 的员工");
                             User missing = new User();
                             missing.setName(currentEmployeeName[0]);
                             missing.setJobNumber(currentJobNumber[0]);

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

@@ -40,4 +40,6 @@ public interface CompanyDingdingService extends IService<CompanyDingding> {
     public void sendInnerLinkMsg(CompanyDingding dingding, String useridList, String title, String alertMsg);
 
     HttpRespMsg getSearchUserInfo(CompanyDingding dingding, String name, Integer searchType) throws Exception;
+
+
 }

+ 10 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java

@@ -65,4 +65,14 @@ public interface DingDingService {
     HttpRespMsg refreshUserCardTime(Integer companyId, String userId, String date);
 
     UserDingdingTime listUserScheduleByDay(Integer companyId, String userId, String date);
+
+    /**
+     * 获取员工的考勤打卡记录
+     * @param companyId 公司ID
+     * @param userIds 员工ID列表,多个用逗号分隔
+     * @param workDateFrom 开始日期 格式:yyyy-MM-dd
+     * @param workDateTo 结束日期 格式:yyyy-MM-dd
+     * @return 考勤打卡记录
+     */
+    HttpRespMsg getAttendanceScheduleResult(Integer companyId, String userIds, String workDateFrom, String workDateTo);
 }

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

@@ -344,4 +344,6 @@ public interface ProjectService extends IService<Project> {
     void syncHongHuData(int honghuCompId);
 
     HttpRespMsg fixQingJianData();
+
+    HttpRespMsg getRemainingTime(Integer projectId, HttpServletRequest request);
 }

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/CompanyDingdingServiceImpl.java

@@ -36,6 +36,7 @@ import javax.annotation.Resource;
 import java.net.URLEncoder;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.List;
@@ -635,4 +636,6 @@ public class CompanyDingdingServiceImpl extends ServiceImpl<CompanyDingdingMappe
         return msg;
     }
 
+
+
 }

+ 110 - 12
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java

@@ -2247,15 +2247,6 @@ public class DingDingServiceImpl implements DingDingService {
             userList.add(userMapper.selectById(targetUserId));
         } else {
             userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", dingding.getCompanyId()).eq("is_active", 1));
-//            for (User user : userList) {
-//                if (user.getName().equals("杨云鑫")) {
-//                    System.out.println("杨云鑫。。。。" + user.getDingdingUserid());
-//                    List<User> nbewList = new ArrayList<>();
-//                    nbewList.add(user);
-//                    userList = nbewList;
-//                    break;
-//                }
-//            }
         }
         String accessToken = getCorpAccessToken(dingding);
         if (userList.size() > 50) {
@@ -2949,13 +2940,11 @@ public class DingDingServiceImpl implements DingDingService {
                         //第一天
                         long seconds = end.toEpochSecond(ZoneOffset.ofHours(8)) - start.toEpochSecond(ZoneOffset.ofHours(8));
                         double workHours = DateTimeUtil.getHoursFromDouble(DateTimeUtil.getHoursFromSeconds((int) seconds));
-                        System.out.println("出差时长=="+workHours);
                         userDingdingTime.setWorkHours((float)workHours);
                     } else if (endDateStr.equals(date)) {
                         //最后一天
                         long seconds = end.toEpochSecond(ZoneOffset.ofHours(8)) - start.toEpochSecond(ZoneOffset.ofHours(8));
                         double workHours = DateTimeUtil.getHoursFromDouble(DateTimeUtil.getHoursFromSeconds((int) seconds));
-                        System.out.println("出差时长=="+workHours);
                         userDingdingTime.setWorkHours((float)workHours);
                     } else {
                         //中间天,就是全天
@@ -2972,7 +2961,6 @@ public class DingDingServiceImpl implements DingDingService {
                     //就是当天,计算时长
                     long seconds = end.toEpochSecond(ZoneOffset.ofHours(8)) - start.toEpochSecond(ZoneOffset.ofHours(8));
                     double workHours = DateTimeUtil.getHoursFromDouble(DateTimeUtil.getHoursFromSeconds((int) seconds));
-                    System.out.println("出差时长=="+workHours);
                     userDingdingTime.setWorkHours((float)workHours);
                 }
                 if (userDingdingTime.getWorkHours() > 8.0) {
@@ -3009,4 +2997,114 @@ public class DingDingServiceImpl implements DingDingService {
         }
         return deptId;
     }
+
+    private List<Long> getSchedulePlanIds(String accessToken, String workDate, String userId, long offset) {
+        List<Long> planIds = new ArrayList<>();
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/listschedule");
+        OapiAttendanceListscheduleRequest req = new OapiAttendanceListscheduleRequest();
+        req.setWorkDate(StringUtils.parseDateTime(workDate + " 11:11:11"));
+        req.setOffset(offset);
+        req.setSize(200L);
+        OapiAttendanceListscheduleResponse rsp = null;
+        try {
+            rsp = client.execute(req, accessToken);
+            System.out.println(rsp.getBody());
+            JSONObject jsonObject = JSONObject.parseObject(rsp.getBody());
+            if (jsonObject.getInteger("errcode") == 0) {
+                JSONObject resultObj = jsonObject.getJSONObject("result");
+                Boolean hasMore = resultObj.getBoolean("has_more");
+                JSONArray jsonArray = resultObj.getJSONArray("schedules");
+                /**
+                 *数据格式为 {
+                 *                     "check_type": "OnDuty",
+                 *                     "class_id": 677995086,
+                 *                     "class_setting_id": 599315627,
+                 *                     "group_id": 685935028,
+                 *                     "plan_check_time": "2020-11-11 09:30:00",
+                 *                     "plan_id": 157062792171,
+                 *                     "userid": "user01"
+                 *                }
+                 */
+
+                for (int i=0;i<jsonArray.size(); i++) {
+                    JSONObject scheduleObj = jsonArray.getJSONObject(i);
+                    String planId = scheduleObj.getString("plan_id");
+                    String userIdStr = scheduleObj.getString("userid");
+                    if (userIdStr.equals(userId)) {
+                        planIds.add(Long.parseLong(planId));
+                    }
+                }
+                if (hasMore) {
+                    List<Long> list = getSchedulePlanIds(accessToken, workDate, userId, offset+200);
+                    if (list.size() > 0) {
+                        planIds.addAll(list);
+                    }
+                }
+            }
+        } catch (ApiException e) {
+            throw new RuntimeException(e);
+        }
+        return planIds;
+    }
+
+    /**
+     * 获取员工的考勤打卡记录
+     * 调用钉钉接口:https://oapi.dingtalk.com/topapi/attendance/schedule/result/listbyids
+     * 参考文档:https://open.dingtalk.com/document/development/query-the-results-of-a-batch-of-tasks
+     * @param companyId 公司ID
+     * @param userId 员工钉钉ID列表,多个用逗号分隔
+     * @param workDateFrom 开始日期 格式:yyyy-MM-dd
+     * @param workDateTo 结束日期 格式:yyyy-MM-dd
+     * @return 考勤打卡记录
+     */
+    @Override
+    public HttpRespMsg getAttendanceScheduleResult(Integer companyId, String userId, String workDateFrom, String workDateTo) {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            // 获取公司钉钉配置信息
+            CompanyDingding dingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", companyId));
+            if (dingding == null) {
+                msg.setError("未找到公司钉钉配置信息");
+                return msg;
+            }
+
+            // 获取accessToken
+            String accessToken = getCorpAccessToken(dingding);
+            if (accessToken == null) {
+                msg.setError("获取accessToken失败");
+                return msg;
+            }
+
+            List<Long> planIds = getSchedulePlanIds(accessToken, workDateFrom, userId, 0);
+            System.out.println("planIds===="+planIds);
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/schedule/result/listbyids");
+            OapiAttendanceScheduleResultListbyidsRequest req = new OapiAttendanceScheduleResultListbyidsRequest();
+            String oaManagerDid = dingding.getOaManagerDingid();
+            req.setOpUserId(oaManagerDid);
+            String planIdsString = planIds.stream().map(Object::toString).collect(Collectors.joining(","));
+            req.setScheduleIds(planIdsString);
+            OapiAttendanceScheduleResultListbyidsResponse rsp = client.execute(req, accessToken);
+            System.out.println(rsp.getBody());
+            // 解析返回结果
+            JSONObject json = JSONObject.parseObject(rsp.getBody());
+            if (json.getInteger("errcode") == 0) {
+                // 成功获取数据
+                msg.data = json.getJSONObject("result");
+                System.out.println("成功获取考勤打卡记录,员工ID:" + userId + ",日期范围:" + workDateFrom + " 至 " + workDateTo);
+            } else {
+                // 接口返回错误
+                msg.setError("钉钉接口返回错误:" + json.getString("errmsg"));
+                System.err.println("获取考勤打卡记录失败:" + json.getString("errmsg"));
+            }
+
+        } catch (ApiException e) {
+            e.printStackTrace();
+            msg.setError("调用钉钉接口异常:" + e.getMessage());
+        } catch (Exception e) {
+            e.printStackTrace();
+            msg.setError("获取考勤打卡记录异常:" + e.getMessage());
+        }
+
+        return msg;
+    }
 }

+ 37 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -2558,7 +2558,10 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 projectMapper.cleanPublicProjectData(id);
             }
         }
-        //250214新需求:添加项目部门关联关系
+        //250214新需求:添加项目部门关联关系,先清空之前的表
+        projectDeptRelateMapper.delete(new LambdaQueryWrapper<ProjectDeptRelate>()
+                .eq(ProjectDeptRelate::getProjectId,id)
+        );
         if(org.apache.commons.lang3.StringUtils.isNotBlank(deptIds)){
             List<String> deptList = null;
             try {
@@ -2567,13 +2570,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 httpRespMsg.setError("部门解析失败");
                 return httpRespMsg;
             }
-            projectDeptRelateMapper.delete(new LambdaQueryWrapper<ProjectDeptRelate>()
-                    .eq(ProjectDeptRelate::getProjectId,id)
-            );
             if(CollectionUtils.isNotEmpty(deptList)&&id!=null){
                 projectDeptRelateMapper.insertBatch(id,deptList);
             }
-
         }
         return httpRespMsg;
     }
@@ -14312,6 +14311,39 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return msg;
     }
 
+    @Override
+    public HttpRespMsg getRemainingTime(Integer projectId, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        Project project = projectMapper.selectById(projectId);
+        if(project.getManDay()!=null){
+            TimeType timeType = timeTypeMapper.selectById(project.getCompanyId());
+            BigDecimal bigDecimal=new BigDecimal(project.getManDay());
+            bigDecimal=bigDecimal.multiply(new BigDecimal(timeType.getAllday()));
+            String format = String.format("%.1f", bigDecimal.doubleValue());
+            project.setEstimatedWorkTime(format);
+            //todo:计算剩余工时
+            QueryWrapper<Report> queryWrapper = new QueryWrapper<>();
+            queryWrapper.select("project_id, sum(working_time) as working_time").eq("project_id", projectId)
+                    .and(wrapper -> wrapper.eq("state", 0).or().eq("state", 1)
+                            ).groupBy("project_id");
+            if(project.getManDayStartDate()!=null){
+                //reports = reportList.stream().filter(rl -> rl.getProjectId().equals(project.getId())&&(rl.getCreateDate().isAfter(project.getManDayStartDate())||rl.getCreateDate().isEqual(project.getManDayStartDate()))).collect(Collectors.toList());
+                queryWrapper.ge("create_date",project.getManDayStartDate());
+            }
+            Report report = reportMapper.selectOne(queryWrapper);
+            if (report == null) {
+                msg.data = String.format("%.1fh", bigDecimal.doubleValue());
+            } else {
+                bigDecimal=bigDecimal.subtract(new BigDecimal(report.getWorkingTime()));
+                msg.data = String.format("%.1fh", bigDecimal.doubleValue());
+            }
+        } else {
+            msg.data = "无限制";
+        }
+
+        return msg;
+    }
+
     public void initGroup(Integer companyId, Integer projectId) {
         User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                 .eq(User::getRoleName, "超级管理员")

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet-workshop/config/index.js

@@ -4,7 +4,7 @@ var path = require('path')
 // var ip = '47.101.180.183'
 // var ip = '47.100.37.243'
 // var ip = '192.168.10.2'
-//var ip = '192.168.2.12'
+// var ip = '43.137.14.81'
 
 var os = require('os'), ip = '', ifaces = os.networkInterfaces() // 获取本机ip
 for (var i in ifaces) {

+ 141 - 3
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/demo_index.html

@@ -54,6 +54,42 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe619;</span>
+                <div class="name">bug</div>
+                <div class="code-name">&amp;#xe619;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe76f;</span>
+                <div class="name">location</div>
+                <div class="code-name">&amp;#xe76f;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe61f;</span>
+                <div class="name">立项审批</div>
+                <div class="code-name">&amp;#xe61f;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe618;</span>
+                <div class="name">产品</div>
+                <div class="code-name">&amp;#xe618;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe69a;</span>
+                <div class="name">智能优化</div>
+                <div class="code-name">&amp;#xe69a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe772;</span>
+                <div class="name">钉钉</div>
+                <div class="code-name">&amp;#xe772;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe625;</span>
                 <div class="name">推送</div>
@@ -492,9 +528,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1672729800404') format('woff2'),
-       url('iconfont.woff?t=1672729800404') format('woff'),
-       url('iconfont.ttf?t=1672729800404') format('truetype');
+  src: url('iconfont.woff2?t=1766996481311') format('woff2'),
+       url('iconfont.woff?t=1766996481311') format('woff'),
+       url('iconfont.ttf?t=1766996481311') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -520,6 +556,60 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont firerock-iconbug"></span>
+            <div class="name">
+              bug
+            </div>
+            <div class="code-name">.firerock-iconbug
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconlocation"></span>
+            <div class="name">
+              location
+            </div>
+            <div class="code-name">.firerock-iconlocation
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconlixiangshenpi"></span>
+            <div class="name">
+              立项审批
+            </div>
+            <div class="code-name">.firerock-iconlixiangshenpi
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconchanpin"></span>
+            <div class="name">
+              产品
+            </div>
+            <div class="code-name">.firerock-iconchanpin
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconzhinengyouhua"></span>
+            <div class="name">
+              智能优化
+            </div>
+            <div class="code-name">.firerock-iconzhinengyouhua
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-icondingding"></span>
+            <div class="name">
+              钉钉
+            </div>
+            <div class="code-name">.firerock-icondingding
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont firerock-icontuisong"></span>
             <div class="name">
@@ -1177,6 +1267,54 @@
       <div class="content symbol">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconbug"></use>
+                </svg>
+                <div class="name">bug</div>
+                <div class="code-name">#firerock-iconbug</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconlocation"></use>
+                </svg>
+                <div class="name">location</div>
+                <div class="code-name">#firerock-iconlocation</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconlixiangshenpi"></use>
+                </svg>
+                <div class="name">立项审批</div>
+                <div class="code-name">#firerock-iconlixiangshenpi</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconchanpin"></use>
+                </svg>
+                <div class="name">产品</div>
+                <div class="code-name">#firerock-iconchanpin</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconzhinengyouhua"></use>
+                </svg>
+                <div class="name">智能优化</div>
+                <div class="code-name">#firerock-iconzhinengyouhua</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-icondingding"></use>
+                </svg>
+                <div class="name">钉钉</div>
+                <div class="code-name">#firerock-icondingding</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#firerock-icontuisong"></use>

+ 27 - 3
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2390497 */
-  src: url('iconfont.woff2?t=1672729800404') format('woff2'),
-       url('iconfont.woff?t=1672729800404') format('woff'),
-       url('iconfont.ttf?t=1672729800404') format('truetype');
+  src: url('iconfont.woff2?t=1766996481311') format('woff2'),
+       url('iconfont.woff?t=1766996481311') format('woff'),
+       url('iconfont.ttf?t=1766996481311') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,30 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.firerock-iconbug:before {
+  content: "\e619";
+}
+
+.firerock-iconlocation:before {
+  content: "\e76f";
+}
+
+.firerock-iconlixiangshenpi:before {
+  content: "\e61f";
+}
+
+.firerock-iconchanpin:before {
+  content: "\e618";
+}
+
+.firerock-iconzhinengyouhua:before {
+  content: "\e69a";
+}
+
+.firerock-icondingding:before {
+  content: "\e772";
+}
+
 .firerock-icontuisong:before {
   content: "\e625";
 }

Diff do ficheiro suprimidas por serem muito extensas
+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.js


+ 42 - 0
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.json

@@ -5,6 +5,48 @@
   "css_prefix_text": "firerock-icon",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "5524676",
+      "name": "bug",
+      "font_class": "bug",
+      "unicode": "e619",
+      "unicode_decimal": 58905
+    },
+    {
+      "icon_id": "2510117",
+      "name": "location",
+      "font_class": "location",
+      "unicode": "e76f",
+      "unicode_decimal": 59247
+    },
+    {
+      "icon_id": "12762893",
+      "name": "立项审批",
+      "font_class": "lixiangshenpi",
+      "unicode": "e61f",
+      "unicode_decimal": 58911
+    },
+    {
+      "icon_id": "4464993",
+      "name": "产品",
+      "font_class": "chanpin",
+      "unicode": "e618",
+      "unicode_decimal": 58904
+    },
+    {
+      "icon_id": "666901",
+      "name": "智能优化",
+      "font_class": "zhinengyouhua",
+      "unicode": "e69a",
+      "unicode_decimal": 59034
+    },
+    {
+      "icon_id": "20375943",
+      "name": "钉钉",
+      "font_class": "dingding",
+      "unicode": "e772",
+      "unicode_decimal": 59250
+    },
     {
       "icon_id": "10936691",
       "name": "推送",

BIN
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.ttf


BIN
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.woff


BIN
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.woff2


+ 3 - 3
fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue

@@ -855,9 +855,9 @@ export default {
         viewList: [{id:1,name:this.$t('alltaskss')},{id:2,name:this.$t('taskinprogress')},{id:3,name:this.$t('missionscompleted')},{id:4,name:this.$t('taskscheduled')},
         {id:5,name:this.$t('createdthetask')},{id:6,name:this.$t('missionIwason')},{id:7,name:this.$t('todaytask')},{id:8,name:this.$t('taskthatisoverdue')}],
         importanceList:[{id:0,name:this.$t('yi-ban')},{id:1,name:this.$t('zhong-yao')},{id:2,name:this.$t('jin-ji')},],
-        taskTypeList:[{id:0,name:this.$t('other.task'), icon:"iconfont firerock-iconrenwu"},{id:1,name:this.$t('other.milestone'),icon:"iconfont firerock-iconicon-"},{id:2,name:this.$t('risk'),icon:"iconfont firerock-iconfengxian"}],
-        taskTypeColor:[getThemeColor(),'#8613ad','#bf0404'],
-        taskTypeIcon:['iconfont firerock-iconrenwu','iconfont firerock-iconicon-','iconfont firerock-iconfengxian'],
+        taskTypeList:[{id:0,name:this.$t('other.task'), icon:"iconfont firerock-iconrenwu"},{id:1,name:this.$t('other.milestone'),icon:"iconfont firerock-iconicon-"},{id:2,name:this.$t('risk'),icon:"iconfont firerock-iconfengxian"}, {id:3, name:'BUG', icon: "iconfont firerock-iconbug"}],
+        taskTypeColor:[getThemeColor(),'#8613ad','#bf0404','#ff0000'],
+        taskTypeIcon:['iconfont firerock-iconrenwu','iconfont firerock-iconicon-','iconfont firerock-iconfengxian','iconfont firerock-iconbug'],
         taskStatusList:[this.$t('ongoing'),this.$t('state.completed'),this.$t('state.undone')],
         //优先级
         taskLevelColor:['#262626','#E6A23C','#F56C6C'],

+ 2 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -2254,8 +2254,8 @@ export default {
       addFormVisible:false,
       title:'',
       childrenList:[],
-      taskTypeTxt:[this.$t('other.task'), this.$t('other.milestone'), this.$t('risk')],
-      taskTypeObj: [{id: '0',value: this.$t('other.task')},{id: '1',value: this.$t('other.milestone')},{id: '2',value: this.$t('risk')}],
+      taskTypeTxt:[this.$t('other.task'), this.$t('other.milestone'), this.$t('risk'), 'BUG'],
+      taskTypeObj: [{id: '0',value: this.$t('other.task')},{id: '1',value: this.$t('other.milestone')},{id: '2',value: this.$t('risk')},{id: '3',value: 'BUG'}],
       taskTypeId: null,
       taskStatusTxt:[this.$t('ongoing'),this.$t('state.completed'),this.$t('state.undone')],
       statusTxt:["-",this.$t('ongoing'),this.$t('state.completed'),this.$t('state.undone')],

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/project/gantt.vue

@@ -214,7 +214,7 @@ export default {
         type_task: this.$t('other.task'),
         type_project: this.$t('other.project'),
         type_milestone: this.$t('other.milestone'),
-
+        type_bug: 'BUG',
         minutes: this.$t('fenZhong'),
         hours: this.$t('time.hour'),
         days: this.$t('time.day'),

+ 3 - 3
fhKeeper/formulahousekeeper/timesheet/src/views/project/projectInside.vue

@@ -1360,9 +1360,9 @@
                 viewList: [{id:1,name:this.$t('alltaskss')},{id:2,name:this.$t('taskinprogress')},{id:3,name:this.$t('missionscompleted')},{id:4,name:this.$t('taskscheduled')},
                 {id:5,name:this.$t('createdthetask')},{id:6,name:this.$t('missionIwason')},{id:7,name:this.$t('todaytask')},{id:8,name:this.$t('taskthatisoverdue')}],
                 importanceList:[{id:0,name:this.$t('yi-ban')},{id:1,name:this.$t('zhong-yao')},{id:2,name:this.$t('jin-ji')},],
-                taskTypeList:[{id:0,name:this.$t('other.task'), icon:"iconfont firerock-iconrenwu"},{id:1,name:this.$t('other.milestone'),icon:"iconfont firerock-iconicon-"},{id:2,name:this.$t('risk'),icon:"iconfont firerock-iconfengxian"}],
-                taskTypeColor:[getThemeColor(),'#8613ad','#bf0404'],
-                taskTypeIcon:['iconfont firerock-iconrenwu','iconfont firerock-iconicon-','iconfont firerock-iconfengxian'],
+                taskTypeList:[{id:0,name:this.$t('other.task'), icon:"iconfont firerock-iconrenwu"},{id:1,name:this.$t('other.milestone'),icon:"iconfont firerock-iconicon-"},{id:2,name:this.$t('risk'),icon:"iconfont firerock-iconfengxian"}, {id:3, name:'BUG', icon: "iconfont firerock-iconbug"}],
+                taskTypeColor:[getThemeColor(),'#8613ad','#bf0404','#ff0000'],
+        taskTypeIcon:['iconfont firerock-iconrenwu','iconfont firerock-iconicon-','iconfont firerock-iconfengxian','iconfont firerock-iconbug'],
                 taskStatusList:[this.$t('ongoing'),this.$t('state.completed'),this.$t('state.undone')],
                 //优先级
                 taskLevelColor:['#262626','#E6A23C','#F56C6C'],

+ 1 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/task/list.vue

@@ -41,6 +41,7 @@
                             <el-option :label="$t('other.task')" value="0"></el-option>
                             <el-option :label="$t('other.milestone')" value="1"></el-option>
                             <el-option :label="$t('risk')" value="2"></el-option>
+                            <el-option label="BUG" value="3"></el-option>
                         </el-select>
                     </div>
                 </el-form-item>

+ 2 - 1
fhKeeper/formulahousekeeper/timesheet_mld/src/components/taskComponent.vue

@@ -387,7 +387,8 @@
     <div slot="footer" class="dialog-footer foooot">
         <!-- <el-button v-if="(user.id == showMmeiLaiDeData.checkFirstId && showMmeiLaiDeData.taskStatus == 3) || (user.id == showMmeiLaiDeData.checkSecondId && [4, '4', '1', 1].includes(showMmeiLaiDeData.taskStatus))" @click.native="deleteTask()" style="float:left;">{{ $t('btn.delete') }}</el-button>
         <el-button v-if="showMmeiLaiDeData.taskPlan && showMmeiLaiDeData.taskStatus == 2" @click.native="deleteTask()" style="float:left;">删除</el-button> -->
-        <el-button v-if="addForm.createrId == user.id && addForm.taskStatus == 2" @click.native="deleteTask()" style="float:left;">删除</el-button>
+        <!--在已撤回或者被驳回的情况下可以删除-->
+        <el-button v-if="addForm.createrId == user.id && (addForm.taskStatus == 2 || addForm.taskStatus == 5 || addForm.taskStatus == 6)" @click.native="deleteTask()" style="float:left;">删除</el-button>
         <el-button @click.native="closeBounceds()">{{ $t('btn.cancel') }}</el-button>
 
         <template v-if="addForm.taskStatus == 3 && addForm.createrId == user.id">