소스 검색

Merge branch 'master' of http://47.100.37.243:10080/wutt/manHourHousekeeper

cs 2 년 전
부모
커밋
7133a3c8a6
31개의 변경된 파일16219개의 추가작업 그리고 647개의 파일을 삭제
  1. 10 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  2. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  3. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  4. 36 36
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java
  5. 81 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  6. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  7. 49 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  8. 3 0
      fhKeeper/formulahousekeeper/octopus/src/views/customer/list.vue
  9. 13 2
      fhKeeper/formulahousekeeper/octopus/src/views/workReport/review.vue
  10. 4 1
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/controller/OperationRecordController.java
  11. 51 5
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/demo_index.html
  12. 11 3
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.css
  13. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.js
  14. 14 0
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.json
  15. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.ttf
  16. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.woff
  17. BIN
      fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.woff2
  18. 50 15
      fhKeeper/formulahousekeeper/timesheet/src/components/select.vue
  19. 4 1
      fhKeeper/formulahousekeeper/timesheet/src/permissions.js
  20. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/routes.js
  21. 32 2
      fhKeeper/formulahousekeeper/timesheet/src/views/contract/index.vue
  22. 61 6
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  23. 3 2
      fhKeeper/formulahousekeeper/timesheet/src/views/project/finance.vue
  24. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/projectInside.vue
  25. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/task/list.vue
  26. 15585 555
      fhKeeper/formulahousekeeper/timesheet_h5/package-lock.json
  27. 2 0
      fhKeeper/formulahousekeeper/timesheet_h5/package.json
  28. 109 0
      fhKeeper/formulahousekeeper/timesheet_h5/src/main.js
  29. 69 10
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/task/editask.vue
  30. 12 2
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/task/index.vue
  31. 5 3
      fhKeeper/formulahousekeeper/timesheet_h5/vue.config.js

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

@@ -1157,5 +1157,15 @@ public class ProjectController {
         return projectService.exportProjectGroupAndCategoryWorkTime(request,startDate,endDate,projectId);
     }
 
+    @RequestMapping("/getSubProjectTimeCost")
+    public HttpRespMsg getSubProjectTimeCost(HttpServletRequest request,String startDate,String endDate,Integer projectId,Integer pageIndex,Integer pageSize){
+        return projectService.getSubProjectTimeCost(request,startDate,endDate,projectId,pageIndex,pageSize);
+    }
+
+    @RequestMapping("/exportSubProjectTimeCost")
+    public HttpRespMsg exportSubProjectTimeCost(HttpServletRequest request,Integer projectId){
+        return projectService.exportSubProjectTimeCost(request,projectId);
+    }
+
 }
 

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

@@ -140,4 +140,8 @@ public interface ProjectMapper extends BaseMapper<Project> {
     List<Map<String, Object>> getProjectGroupAndCategoryData(String startDate, String endDate, Integer projectId, Integer companyId, Integer start, Integer size, List<Integer> inchagerIds);
 
     long getProjectGroupAndCategoryCount(String startDate, String endDate, Integer projectId, Integer companyId, Integer start, Integer size, List<Integer> inchagerIds);
+
+    List<Map<String, Object>> getSubProjectTimeCost(Integer companyId, String startDate, String endDate, Integer projectId,Integer start,Integer size, List<Integer> inchagerIds);
+
+    long countWithSubProjectTimeCost(Integer companyId, String startDate, String endDate, Integer projectId, Integer start,Integer size, List<Integer> inchagerIds);
 }

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

@@ -217,4 +217,8 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg projectGroupAndCategoryWorkTime(HttpServletRequest request, String startDate, String endDate, Integer projectId,Integer pageIndex,Integer pageSize);
 
     HttpRespMsg exportProjectGroupAndCategoryWorkTime(HttpServletRequest request, String startDate, String endDate, Integer projectId);
+
+    HttpRespMsg getSubProjectTimeCost(HttpServletRequest request, String startDate, String endDate, Integer projectId,Integer pageIndex,Integer pageSize);
+
+    HttpRespMsg exportSubProjectTimeCost(HttpServletRequest request, Integer projectId);
 }

+ 36 - 36
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java

@@ -1003,18 +1003,18 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                             }
                             Finance userFinance = first.get();
 
-                            BigDecimal cost = userFinance.getTotalCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal salary = userFinance.getMonthCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal bonus = userFinance.getBonus().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal allowance = userFinance.getAllowance().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal old = userFinance.getInsuranceOld().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal medical = userFinance.getInsuranceMedical().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal loseJob = userFinance.getInsuranceLosejob().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal injury = userFinance.getInsuranceInjury().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal house = userFinance.getHouseFund().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal field1 = userFinance.getCustomField1() == null? new BigDecimal(0):userFinance.getCustomField1().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal field2 = userFinance.getCustomField2() == null? new BigDecimal(0):userFinance.getCustomField2().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-                            BigDecimal field3 = userFinance.getCustomField3() == null? new BigDecimal(0):userFinance.getCustomField3().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal cost = userFinance.getTotalCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal salary = userFinance.getMonthCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal bonus = userFinance.getBonus().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal allowance = userFinance.getAllowance().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal old = userFinance.getInsuranceOld().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal medical = userFinance.getInsuranceMedical().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal loseJob = userFinance.getInsuranceLosejob().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal injury = userFinance.getInsuranceInjury().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal house = userFinance.getHouseFund().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal field1 = userFinance.getCustomField1() == null? new BigDecimal(0):userFinance.getCustomField1().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal field2 = userFinance.getCustomField2() == null? new BigDecimal(0):userFinance.getCustomField2().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
+                            BigDecimal field3 = userFinance.getCustomField3() == null? new BigDecimal(0):userFinance.getCustomField3().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 6, BigDecimal.ROUND_HALF_UP);
                             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                                 membRowData.add("$userName="+(us.getCorpwxUserid()==null?"":us.getCorpwxUserid())+"$");
                             }else {
@@ -1040,25 +1040,25 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                                 }
                             }
                             membRowData.add(workingTime+"");
-                            membRowData.add(salary.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                            membRowData.add(bonus.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                            membRowData.add(allowance.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                            membRowData.add(old.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                            membRowData.add(medical.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                            membRowData.add(loseJob.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                            membRowData.add(injury.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                            membRowData.add(house.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(salary.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(bonus.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(allowance.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(old.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(medical.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(loseJob.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(injury.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(house.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                             //自定义字段
                             if (cusColList.size() > 0) {
-                                membRowData.add(field1.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                membRowData.add(field1.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                             }
                             if (cusColList.size() > 1) {
-                                membRowData.add(field2.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                membRowData.add(field2.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                             }
                             if (cusColList.size() > 2) {
-                                membRowData.add(field3.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                membRowData.add(field3.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                             }
-                            membRowData.add(cost.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                            membRowData.add(cost.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                             allList.add(membRowData);
                         }
                     }
@@ -1118,25 +1118,25 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                                         }
                                     }
                                     membRowData.add(workingTime+"");
-                                    membRowData.add(salary.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                                    membRowData.add(bonus.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                                    membRowData.add(allowance.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                                    membRowData.add(old.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                                    membRowData.add(medical.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                                    membRowData.add(loseJob.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                                    membRowData.add(injury.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
-                                    membRowData.add(house.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(salary.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(bonus.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(allowance.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(old.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(medical.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(loseJob.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(injury.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(house.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                                     //自定义字段
                                     if (cusColList.size() > 0) {
-                                        membRowData.add(field1.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                        membRowData.add(field1.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                                     }
                                     if (cusColList.size() > 1) {
-                                        membRowData.add(field2.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                        membRowData.add(field2.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                                     }
                                     if (cusColList.size() > 2) {
-                                        membRowData.add(field3.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                        membRowData.add(field3.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                                     }
-                                    membRowData.add(cost.setScale(3, BigDecimal.ROUND_HALF_UP).toPlainString());
+                                    membRowData.add(cost.setScale(6, BigDecimal.ROUND_HALF_UP).toPlainString());
                                     allList.add(membRowData);
                                 }
                             }

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

@@ -8945,6 +8945,87 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return msg;
     }
 
+    @Override
+    public HttpRespMsg getSubProjectTimeCost(HttpServletRequest request, String startDate, String endDate, Integer projectId,Integer pageIndex,Integer pageSize) {
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer start = (pageIndex-1)*pageSize;
+        Integer size = pageSize*pageIndex;
+        User user = userMapper.selectById(request.getHeader("token"));
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", user.getCompanyId()));
+        List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "全部子项目工时成本");
+        List<SysRichFunction> functionInchargeList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "负责项目子项目工时成本");
+        //判断查看权限
+        List<Integer> inchagerIds=null;
+        if(functionAllList.size()==0){
+            inchagerIds=new ArrayList<>();
+            if(functionInchargeList.size()>0){
+                List<Project> list = projectList.stream().filter(pl -> (pl.getInchargerId()==null?0:pl.getInchargerId()).equals(user.getId())).collect(Collectors.toList());
+                if(list!=null){
+                    List<Integer> collect = list.stream().map(li -> li.getId()).collect(Collectors.toList());
+                    inchagerIds.addAll(collect);
+                }
+            }else {
+                inchagerIds.add(-1);
+            }
+        }
+        List<Map<String,Object>> list=projectMapper.getSubProjectTimeCost(companyId,startDate,endDate,projectId,start,size,inchagerIds);
+        long total=projectMapper.countWithSubProjectTimeCost(companyId,startDate,endDate,projectId,null,null,inchagerIds);
+        Map<String,Object> map=new HashMap<>();
+        map.put("record",list);
+        map.put("total",total);
+        msg.data=map;
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg exportSubProjectTimeCost(HttpServletRequest request, Integer projectId) {
+        HttpRespMsg msg=new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", user.getCompanyId()));
+        List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "全部子项目工时成本");
+        List<SysRichFunction> functionInchargeList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "负责项目子项目工时成本");
+        //判断查看权限
+        List<Integer> inchagerIds=null;
+        if(functionAllList.size()==0){
+            inchagerIds=new ArrayList<>();
+            if(functionInchargeList.size()>0){
+                List<Project> list = projectList.stream().filter(pl -> (pl.getInchargerId()==null?0:pl.getInchargerId()).equals(user.getId())).collect(Collectors.toList());
+                if(list!=null){
+                    List<Integer> collect = list.stream().map(li -> li.getId()).collect(Collectors.toList());
+                    inchagerIds.addAll(collect);
+                }
+            }else {
+                inchagerIds.add(-1);
+            }
+        }
+        List<Map<String,Object>> list=projectMapper.getSubProjectTimeCost(companyId,null,null,projectId,null,null,inchagerIds);
+        List<List<String>> dataList=new ArrayList<>();
+        List<String> titleList=new ArrayList<>();
+        titleList.add("项目编号");
+        titleList.add("项目名称");
+        titleList.add("子项目编号");
+        titleList.add("子项目名称");
+        titleList.add("子项目工时");
+        titleList.add("子项目成本");
+        dataList.add(titleList);
+        for (Map<String, Object> map : list) {
+            List<String> item=new ArrayList<>();
+            item.add(String.valueOf(map.get("projectCode")==null?"":map.get("projectCode")));
+            item.add(String.valueOf(map.get("projectName")==null?"":map.get("projectName")));
+            item.add(String.valueOf(map.get("subProjectCode")==null?"":map.get("subProjectCode")));
+            item.add(String.valueOf(map.get("subProjectName")==null?"":map.get("subProjectName")));
+            item.add(String.valueOf(map.get("cost")==null?"0":map.get("cost"))+"(元)");
+            item.add(String.valueOf(map.get("workingTime")==null?"0":map.get("workingTime"))+"(小时)");
+            dataList.add(item);
+        }
+        String fileName = "子项目工时成本表"+System.currentTimeMillis();
+        String resp = ExcelUtil.exportGeneralExcelByTitleAndList(fileName, dataList, path);
+        msg.data=resp;
+        return msg;
+    }
+
     private List<GanttDataItem> getUserGanttDataItemList(GanttDataItem userGantt, List<GanttDataItem> itemList) {
         if(itemList==null){
             itemList=new ArrayList<>();

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

@@ -555,6 +555,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         List<Integer> formIds = companyReportList.stream().map(CompanyReport::getReportFormId).collect(Collectors.toList());
         if (functionIdList.size() > 0) {
             //根据功能id获取可用的操作代码
+            if (formIds.size() == 0) {
+                formIds.add(-1);
+            }
             QueryWrapper<SysFunction> functionQueryWrapper = new QueryWrapper<SysFunction>().and(wrapper1->wrapper1.isNull("report_form_id").or().in("report_form_id",formIds)).and(wrapper->{
                 wrapper.eq("package_time", 1);
                 if (company.getPackageProject() == 1) {

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

@@ -175,6 +175,55 @@
         ORDER BY a.id ASC
     </select>
 
+    <!--获取查询者所在公司每个子项目的工时成本-->
+    <select id="getSubProjectTimeCost" resultType="java.util.Map">
+        select b.project_code as projectCode,b.project_name as projectName,a.code as subProjectCode,a.name as subProjectName,SUM(c.cost) as cost,SUM(c.working_time) as workingTime
+        from sub_project a
+        left join project b on b.id=a.project_id
+        left join report c on c.sub_project_id=a.id
+        where a.company_id=#{companyId}
+        <if test="startDate != null and endDate != null">
+            and c.create_date between #{startDate} and #{endDate}
+        </if>
+        <if test="projectId!=null">
+            and a.project_id=#{projectId}
+        </if>
+        <if test="inchagerIds!=null and inchagerIds.size()>0">
+            and b.id in
+            <foreach collection="inchagerIds" open="(" close=")" separator="," item="item">
+                #{item}
+            </foreach>
+        </if>
+        group by b.id,a.id
+        <if test="start!=null and size!=null">
+            limit #{start},#{size}
+        </if>
+    </select>
+
+    <select id="countWithSubProjectTimeCost" resultType="java.lang.Long">
+        select count(1) from(select b.project_code as projectCode,b.project_name as projectName,a.code as subProjectCode,a.name as subProjectName,SUM(c.cost) as cost,SUM(c.working_time) as workingTime
+        from sub_project a
+        left join project b on b.id=a.project_id
+        left join report c on c.sub_project_id=a.id
+        where a.company_id=#{companyId}
+        <if test="startDate != null and endDate != null">
+            and c.create_date between #{startDate} and #{endDate}
+        </if>
+        <if test="projectId!=null">
+            and a.project_id=#{projectId}
+        </if>
+        <if test="inchagerIds!=null and inchagerIds.size()>0">
+            and b.id in
+            <foreach collection="inchagerIds" open="(" close=")" separator="," item="item">
+                #{item}
+            </foreach>
+        </if>
+        group by b.id,a.id
+        <if test="start!=null and size!=null">
+            limit #{start},#{size}
+        </if>) as total
+    </select>
+
 
 
     <!--获取查询者所在公司每个项目的工时成本-->

+ 3 - 0
fhKeeper/formulahousekeeper/octopus/src/views/customer/list.vue

@@ -210,6 +210,7 @@
                 <el-form-item><el-checkbox v-model="dialogData.reportAutoApprove">是否开启日报自动审核</el-checkbox></el-form-item>
                 <el-form-item><el-checkbox v-model="dialogData.notAllowedNoAttendance">是否开启考勤为0不可填报</el-checkbox></el-form-item>
                 <el-form-item><el-checkbox v-model="dialogData.stageHasEvtime">是否开启预估工时</el-checkbox></el-form-item>
+                <el-form-item><el-checkbox v-model="dialogData.pushReportData">是否开通【推送工时数据】</el-checkbox></el-form-item>
                 <el-form-item><el-checkbox v-model="dialogData.financeAudit">财务导入是否需要审核</el-checkbox></el-form-item>
                 <el-form-item><el-checkbox v-model="dialogData.includeWeekends">批量填报是否包含周末</el-checkbox></el-form-item>
                 <el-form-item><el-checkbox v-model="dialogData.multiWorktime">一个项目下可填报多个时间段工时</el-checkbox></el-form-item>
@@ -375,6 +376,7 @@
                             this.$set(this.dialogData,'reportAutoApprove',res.data.reportAutoApprove ? true : false)
                             this.$set(this.dialogData,'notAllowedNoAttendance',res.data.notAllowedNoAttendance ? true : false)
                             this.$set(this.dialogData,'stageHasEvtime',res.data.stageHasEvtime ? true : false)
+                            this.$set(this.dialogData,'pushReportData',res.data.pushReportData ? true : false)
                             this.$set(this.dialogData,'financeAudit',res.data.financeAudit ? true : false)
                             this.$set(this.dialogData,'includeWeekends',res.data.includeWeekends ? true : false)
                             this.$set(this.dialogData,'multiWorktime',res.data.multiWorktime ? true : false)
@@ -654,6 +656,7 @@
                     reportAutoApprove: this.dialogData.reportAutoApprove ? 1 : 0,
                     notAllowedNoAttendance: this.dialogData.notAllowedNoAttendance ? 1 : 0,
                     stageHasEvtime: this.dialogData.stageHasEvtime ? 1 : 0,
+                    pushReportData: this.dialogData.pushReportData ? 1 : 0,
                     includeWeekends: this.dialogData.includeWeekends ? 1 : 0,
                     multiWorktime: this.dialogData.multiWorktime ? 1 : 0,
                     reportAuditType: this.dialogData.reportAuditType

+ 13 - 2
fhKeeper/formulahousekeeper/octopus/src/views/workReport/review.vue

@@ -5,6 +5,10 @@
                 <el-input id="contractAmount" v-model="paramCompanyName" placeholder="输入公司名称" @keyup.native="restrictNumber('contractAmount')" style="width:200px" clearable size="small">
                     <el-button slot="append" size="small" icon="el-icon-search" @click="toolbarSelect()"></el-button>
                 </el-input>
+
+                <el-input id="contractAmount2" v-model="paramProjectName" placeholder="输入项目名称" @keyup.native="restrictNumber('contractAmount2')" style="width:200px;margin-left:20px" clearable size="small">
+                    <el-button slot="append" size="small" icon="el-icon-search" @click="toolbarSelect()"></el-button>
+                </el-input>
                 
                 <el-date-picker 
                 v-model="dateArray" 
@@ -26,10 +30,15 @@
             <el-table-column prop="moduleName" label="模块" min-width="80"></el-table-column>
             <el-table-column prop="operatorName" label="操作人" min-width="100"></el-table-column>
             <el-table-column prop="time" label="操作时间" min-width="200"></el-table-column>
+            <el-table-column prop="projectName" label="项目名称" min-width="200">
+                <template slot-scope="scope">
+                    <span v-if="scope.row.projectName != 'null' && scope.row.projectName != null">{{scope.row.projectName}}</span>
+                    <span v-else></span>
+                </template>
+            </el-table-column>
             <el-table-column prop="content" label="操作内容" min-width="500">
                 <template slot-scope="scope">
                     <div v-for="item,index in contentString(scope.row.content)" :key="index">{{item}}</div>
-                    <!-- <span>{{contentString(scope.row.content)}}</span> -->
                     <!-- <span>{{scope.row.content}}</span> -->
                 </template>
             </el-table-column>
@@ -63,7 +72,8 @@
 
                 tableList: [],
                 dateArray: [],
-                paramCompanyName: ''
+                paramCompanyName: '',
+                paramProjectName: ''
             }
         },
         created() {
@@ -100,6 +110,7 @@
                     startDate: this.dateArray[0],
                     endDate: this.dateArray[1],
                     companyName: this.paramCompanyName,
+                    projectName: this.paramProjectName,
                     pageIndex: this.page,
                     pageSize: this.size,
                 },res => {

+ 4 - 1
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/controller/OperationRecordController.java

@@ -42,7 +42,7 @@ public class OperationRecordController {
     private CompanyMapper companyMapper;
 
     @RequestMapping("/getList")
-    public HttpRespMsg getList(String companyName,String startDate,String endDate,Integer pageIndex ,Integer pageSize){
+    public HttpRespMsg getList(String companyName,String startDate,String endDate,Integer pageIndex ,Integer pageSize,String projectName){
         HttpRespMsg httpRespMsg=new HttpRespMsg();
         List<Company> companyList = companyMapper.selectList(null);
         QueryWrapper<OperationRecord> queryWrapper=new QueryWrapper<>();
@@ -59,6 +59,9 @@ public class OperationRecordController {
             queryWrapper.ge("operation_time",start);
             queryWrapper.le("operation_time",end);
         }
+        if(projectName!=null){
+            queryWrapper.like("project_name",projectName);
+        }
         queryWrapper.orderByDesc("operation_time");
         IPage<OperationRecord> operationRecordIPage = operationRecordMapper.selectPage(new Page<>(pageIndex, pageSize), queryWrapper);
         List<OperationRecord> list = operationRecordIPage.getRecords();

+ 51 - 5
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/demo_index.html

@@ -3,8 +3,8 @@
 <head>
   <meta charset="utf-8"/>
   <title>iconfont Demo</title>
-  <link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
-  <link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg"/>
+  <link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
+  <link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
   <link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
   <link rel="stylesheet" href="demo.css">
   <link rel="stylesheet" href="iconfont.css">
@@ -54,6 +54,18 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe675;</span>
+                <div class="name">合同7</div>
+                <div class="code-name">&amp;#xe675;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6ca;</span>
+                <div class="name">sync</div>
+                <div class="code-name">&amp;#xe6ca;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe700;</span>
                 <div class="name">流程</div>
@@ -474,9 +486,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1656062511171') format('woff2'),
-       url('iconfont.woff?t=1656062511171') format('woff'),
-       url('iconfont.ttf?t=1656062511171') format('truetype');
+  src: url('iconfont.woff2?t=1671700473139') format('woff2'),
+       url('iconfont.woff?t=1671700473139') format('woff'),
+       url('iconfont.ttf?t=1671700473139') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -502,6 +514,24 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont firerock-iconhetong7"></span>
+            <div class="name">
+              合同7
+            </div>
+            <div class="code-name">.firerock-iconhetong7
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont firerock-iconsync"></span>
+            <div class="name">
+              sync
+            </div>
+            <div class="code-name">.firerock-iconsync
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont firerock-iconliucheng1"></span>
             <div class="name">
@@ -1132,6 +1162,22 @@
       <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-iconhetong7"></use>
+                </svg>
+                <div class="name">合同7</div>
+                <div class="code-name">#firerock-iconhetong7</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#firerock-iconsync"></use>
+                </svg>
+                <div class="name">sync</div>
+                <div class="code-name">#firerock-iconsync</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#firerock-iconliucheng1"></use>

+ 11 - 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=1656062511171') format('woff2'),
-       url('iconfont.woff?t=1656062511171') format('woff'),
-       url('iconfont.ttf?t=1656062511171') format('truetype');
+  src: url('iconfont.woff2?t=1671700473139') format('woff2'),
+       url('iconfont.woff?t=1671700473139') format('woff'),
+       url('iconfont.ttf?t=1671700473139') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,14 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.firerock-iconhetong7:before {
+  content: "\e675";
+}
+
+.firerock-iconsync:before {
+  content: "\e6ca";
+}
+
 .firerock-iconliucheng1:before {
   content: "\e700";
 }

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/assets/iconfont/iconfont.js


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

@@ -5,6 +5,20 @@
   "css_prefix_text": "firerock-icon",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "774469",
+      "name": "合同7",
+      "font_class": "hetong7",
+      "unicode": "e675",
+      "unicode_decimal": 58997
+    },
+    {
+      "icon_id": "5832808",
+      "name": "sync",
+      "font_class": "sync",
+      "unicode": "e6ca",
+      "unicode_decimal": 59082
+    },
     {
       "icon_id": "6970024",
       "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


+ 50 - 15
fhKeeper/formulahousekeeper/timesheet/src/components/select.vue

@@ -36,11 +36,9 @@
     <transition name="el-zoom-in-top">
       <div v-show="show" style="position: relative;z-index: 999;"> 
         <!-- 搜索框 -->
-        <!-- <div class="searchBox">
-            <el-input :placeholder="$t('peaseenterthe')" size="mini" v-model="searchTex" style="width: 150px" @focus="searchBox()">
-                <el-button slot="append" icon="el-icon-search" size="mini" @click="searchLick()"></el-button>
-            </el-input>
-        </div> -->
+        <div class="searchBox" v-if="filterable">
+            <el-input placeholder="请输入名称搜索" size="mini" v-model="searchTex" style="width: 100%" @input="searchLick()" @focus="selectCli()"></el-input>
+        </div>
         <div class="transitionBox" :style="filterable ? 'margin: 30px 0;' : ''">
             <ul class="transitionBoxUl">
                 <li :class="transitionBoxLiIdx == index ? 'liHover' : ''" v-for="(item, index) in options" :key="index" @mouseover="liMouseOver(index)" @click="liClick(item, index)"> 
@@ -178,6 +176,9 @@ export default {
             multiSelectList: [],
             searchTex: '', // 搜索文字
             cursor: '', // 搜索的标记(需传给后端)
+            time: null,//防抖
+            fistArrList: [], // 第一次进来的人员数组
+            fistArrListOne: [], // 第一次进来的人员初始数组
         };
     },
     computed: {},
@@ -277,6 +278,18 @@ export default {
             }
         }
         console.log(this.subject, this.subjectId)
+
+        var thats = this
+        var phoneArr = []
+        setTimeout(()=>{
+            for(var s in thats.subject) {
+                phoneArr.push(thats.subject[s].optionsOId || thats.subject[s].auditorId || thats.subject[s].id) 
+            }
+            thats.fistArrListOne = thats.subject
+        }, 500)
+        
+        thats.fistArrList = phoneArr
+        console.log(thats.fistArrList)
         this.dailyListIndex = this.idx
     },
     methods: {
@@ -353,6 +366,7 @@ export default {
                         name: this.selectName
                     }
                     this.$emit("selectCal", obj)
+                    this.options = this.fistArrListOne
                 }
             }
         },
@@ -371,6 +385,7 @@ export default {
                         idx: this.dailyListIndex
                     }
                     this.$emit("selectCatCli", obj);
+                    this.options = this.fistArrListOne
                 } else {
                     let obj = {
                         id: nameId,
@@ -380,6 +395,7 @@ export default {
                         name: this.selectName
                     }
                     this.$emit("selectCal", obj)
+                    this.options = this.fistArrListOne
                 }
                 this.transitionBoxLiIdx = ''
                 this.show = false
@@ -434,6 +450,7 @@ export default {
                     }
                 }
                 this.$emit("selectCal", obj)
+                this.options = this.fistArrListOne
             }
         },
         deleteMultiSelectList(str) {
@@ -461,25 +478,42 @@ export default {
                 name: this.selectName
             }
             this.$emit("selectCal", obj)
+            this.options = this.fistArrListOne
         },
-        searchBox() {
-            this.selectCli()
-        },
-        // 搜索
+        // searchBox() {
+        //     this.selectCli()
+        // },
+        // // 搜索
         searchLick() {
-            console.log('文字')
-            this.getSimpleActiveUserList()
+            if (this.time != null) {
+                clearTimeout(this.time)
+            }
+            var that = this
+            this.time = setTimeout(() => {
+                that.getSimpleActiveUserList()
+            }, 500)
+            
         },
         // 针对  getSimpleActiveUserList 获取所有人员接口
         getSimpleActiveUserList() {
-            this.http.post('/user/getSimpleActiveUserList', {
+            this.http.post('/user/getEmployeeList', {
+                departmentId: -1,
+                pageIndex: 1,
+                pageSize: 200,
                 keyword: this.searchTex,
-                cursor: this.cursor
+                status: 1,
+                roleId: '',
+                cursor: '',
+                onlyDirect: 0,
             },
             res => {
                 if (res.code == "ok") {
-                    console.log('数据')
-                    this.options = res.data.retUser
+                    var arr = res.data.records.filter((item) => {
+                        if (this.fistArrList.indexOf(item.id) != '-1') {
+                            return item;
+                        }
+                    })
+                    this.options = arr
                     this.cursor = res.data.nextCursor
                 } else {
                     this.$message({
@@ -570,6 +604,7 @@ export default {
     .searchBox {
         position: absolute; 
         width: 100%;
+        top: -9px;
     }
     .transitionBox {
         background: #FFF;

+ 4 - 1
fhKeeper/formulahousekeeper/timesheet/src/permissions.js

@@ -86,6 +86,8 @@ const StringUtil = {
         reportResponsibleDepartmentParticipation: false, // 负责部门参与项目情况表 //
         reportPhaseHours: false, // 全部分组阶段工时 // 
         reportStageWorkingTime: false, // 负责项目分组阶段工时 //
+        reportAllManhourCost: false, // 全部子项目工时成本 //
+        reportResponsibleManhourCost: false, // 负责项目子项目工时成本 //
 
         // 请假模块
         leaveFil : false, // 请假填报 // 
@@ -220,7 +222,8 @@ const StringUtil = {
         arr[i] == '导入合同' ? obj.contractImport = true : ''
         arr[i] == '合同类型管理' ? obj.contractType = true : ''
         arr[i] == '审核合同' ? obj.contractAudit = true : ''
-
+        arr[i] == '全部子项目工时成本' ? obj.reportAllManhourCost = true : ''
+        arr[i] == '负责项目子项目工时成本' ? obj.reportResponsibleManhourCost = true : ''
     }
     return obj
   }

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/routes.js

@@ -290,7 +290,7 @@ export const allRouters = [//组织架构
         path: '/',
         component: Home,
         name: '合同管理',
-        iconCls: 'iconfont firerock-iconxiangmu',
+        iconCls: 'iconfont firerock-iconhetong7',
         leaf: true,
         children: [
             { path: '/contract', component: contract, name: '合同管理' },

+ 32 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/contract/index.vue

@@ -121,6 +121,7 @@
               v-model="contractForm.startDate"
               value-format="yyyy-MM-dd"
               type="date"
+              :picker-options="{disabledDate: disabledStart}"
               :placeholder="$t('optiondate')">
             </el-date-picker>
             <span style="float:right;">{{$t('scheduleendtime')}}
@@ -129,6 +130,7 @@
               v-model="contractForm.endDate"
               value-format="yyyy-MM-dd"
               type="date"
+              :picker-options="{disabledDate: disabledEnd}"
               :placeholder="$t('optiondate')">
             </el-date-picker>
             </span>
@@ -254,7 +256,7 @@
       </div>
       <el-dialog :title="typeTitle == this.$t('add') ? $t('xin-zeng-he-tong-lei-xing') : $t('bian-ji-he-tong-lei-xing')" :visible.sync="typeItemDialog" v-if="typeItemDialog" append-to-body width="400px">
         <div style="height: 12vh;overflow-y: auto;overflow-x: hidden;">
-          <el-input v-model="typeItemForm.typeName"></el-input>
+          <el-input v-model="typeItemForm.typeName" :maxlength="200"></el-input>
         </div>
         <div slot="footer" class="dialog-footer;">
           <el-button type="primary" @click="typeItemDialog = false">{{$t('btn.cancel')}}</el-button>
@@ -379,7 +381,28 @@ export default {
                   }
                 
             },
-
+    disabledStart(date){
+      if(this.contractForm.endDate){
+        if(date > new Date(this.contractForm.endDate)){
+          return true
+        }else{
+          return false
+        }
+      }else{
+        return false
+      }
+    },
+    disabledEnd(date){
+      if(this.contractForm.startDate){
+        if(date < new Date(this.contractForm.startDate)){
+          return true
+        }else{
+          return false
+        }
+      }else{
+        return false
+      }
+    },
     searchFilter(){
       this.page = 1
       this.getContractList()
@@ -479,6 +502,13 @@ export default {
       this.typeDialog = true
     },
     typeItemAdd(){
+      if(this.typeList.length == 20){
+        this.$message({
+          message: '合同类型最多只能创建20个',
+          type: 'error'
+        })
+        return
+      }
       this.typeTitle = this.$t('add')
       this.typeItemForm = {typeName: ''}
       this.typeItemDialog = true

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

@@ -37,6 +37,7 @@
                   <el-menu-item index="1-15" v-if="permissions.reportMonthlyPersonnel || permissions.reportResponsiblePersonnel" @click="ssl(14)"><p>{{ $t('ren-yuan-yue-du-gong-shi-biao') }}</p></el-menu-item>
                   <el-menu-item index="1-16" v-if="permissions.reportAllDepartmentParticipation || permissions.reportResponsibleDepartmentParticipation" @click="ssl(15)"><p>{{ $t('bumenchanyuqingkuang') }}</p></el-menu-item>
                   <el-menu-item index="1-17" v-if="permissions.reportPhaseHours || permissions.reportStageWorkingTime" @click="ssl(16)"><p>{{ $t('xiang-mu-ge-fen-zu-yu-jie-duan-gong-shi-biao') }}</p></el-menu-item>
+                  <el-menu-item index="1-18" v-if="permissions.reportAllManhourCost || permissions.reportResponsibleManhourCost" @click="ssl(17)"><p>子项目工时成本表</p></el-menu-item>
                   <!-- <el-menu-item index="1-12"><p @click="ssl(11)">人员工时统计表</p></el-menu-item> -->
                 </el-submenu>
               </el-menu>
@@ -70,7 +71,7 @@
           </el-select>
         </template>
         <!-- 时间段筛选 -->
-          <template v-if="ins == 6 || ins == 8 || ins == 9 || ins == 10 || ins == 11 || ins == 12 || ins == 5 || ins == 16">
+          <template v-if="ins == 6 || ins == 8 || ins == 9 || ins == 10 || ins == 11 || ins == 12 || ins == 5 || ins == 16 || ins == 17">
             <span>
               <span class="demonstration" style="color:#999;padding:0 10px">
                 {{ ins == 15 ? $t('xiang-mu-chuang-jian-shi-jian-duan') : $t('message.period') }}
@@ -85,7 +86,7 @@
           <el-option label="查看部门审核人" :value="0"></el-option>
         </el-select> -->
         <!-- 项目筛选 -->
-        <el-select v-if="ins != 4 && ins != 8 && ins != 9 && ins != 10 && ins != 11 && ins != 14 && ins != 15" v-model="proJuctId" :placeholder="$t('defaultText.pleaseSelectSnItem')" clearable filterable size="small" @change="selcts()" style="margin-left:10px">
+        <el-select v-if="ins != 4 && ins != 8 && ins != 9 && ins != 10 && ins != 11 && ins != 14 && ins != 15 && ins != 17" v-model="proJuctId" :placeholder="$t('defaultText.pleaseSelectSnItem')" clearable filterable size="small" @change="selcts()" style="margin-left:10px">
           <el-option v-for="(item) in proListOvertime" :key="item.id" :label="item.projectName + (item.projectCode ? item.projectCode : '')" :value="item.id">
             <span style="float: left;color: #8492a6;">{{ item.projectCode }}</span>
             <span style="float: right;font-size: 13px;margin-left: 20px">{{ item.projectName }}</span>
@@ -799,6 +800,16 @@
                 </el-table-column>
             </el-table>
 
+            <!-- 子项目工时成本表 -->
+            <el-table v-if="ins == 17"  key="17" border :data="subprojectArr" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
+                <el-table-column align="center" prop="projectCode" label="父项目编号" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="projectName" label="父项目名称" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="subProjectCode" label="子项目编号" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="subProjectName" label="子项目名称" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="workingTime" label="子项目工时" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="cost" label="子项目成本" min-width="150"></el-table-column>
+            </el-table>
+
         <!--工具条-->
         <el-col :span="24" class="toolbar" v-if="ins != 6">
           <el-pagination
@@ -1066,13 +1077,13 @@ export default {
       this.$t('pojectbalancesheetincomestatement'),this.$t('customerprojectprofitstatement'),this.$t('projectphasetimesheet'),
       this.$t('statisticsofovertimework'),this.$t('timecostearlywarningtable'),this.$t('personneltimeallocationtable'),
       this.$t('statisticsofstafffillingintimerate'),this.$t('dailyreporttobereviewedstatistics'),this.$t('statisticsofpersonnelhours'),this.$t('taskgrouptimesheet'),this.$t('projectcostbaselinetable'),
-      this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao')],
+      this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao'), '子项目工时成本表'],
 
       shuzArr: [this.$t('projectreport'),this.$t('projectTaskReport'),this.$t('projectcoststatement'),
       this.$t('projectbalancesheet'),this.$t('customerprojectincomestatement'),this.$t('projectphasetimesheet'),
       this.$t('statisticsofovertimework'),this.$t('timecostearlywarningtable'),this.$t('personneltimeallocationtable'),
       this.$t('employeereporttimelinessrate'),this.$t('dailyreporttobereviewedstatistics'),this.$t('statisticsofpersonnelhours'),this.$t('taskgrouptimesheet'),this.$t('projectcostbaselinetable'),
-      this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao')],
+      this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao'), '子项目工时成本表'],
 
       ins: 10000,
       user: JSON.parse(sessionStorage.user),
@@ -1134,7 +1145,9 @@ export default {
       },
       exportLoading: false,
       groupingItemsArr: [],
-      groupingItemsArrTitle: []
+      groupingItemsArrTitle: [],
+
+      subprojectArr: []
     };
   },
   computed: {},
@@ -1223,6 +1236,7 @@ export default {
       if(this.permissions.reportMonthlyPersonnel || this.permissions.reportResponsiblePersonnel) {this.ssl(14);this.defaultActive = '1-15';return}
       if(this.permissions.reportAllDepartmentParticipation || this.permissions.reportResponsibleDepartmentParticipation) {this.ssl(15);this.defaultActive = '1-16';return}
       if(this.permissions.reportPhaseHours || this.permissions.reportStageWorkingTime) {this.ssl(16);this.defaultActive = '1-17';return}
+      if(this.permissions.reportAllManhourCost || this.permissions.reportResponsibleManhourCost) {this.ssl(17);this.defaultActive = '1-18';return}
       {this.allWrong = false}
     },
     rowspan(spanArr,position,spanName){
@@ -1464,8 +1478,10 @@ export default {
                   this.getDepartmentsInvolved()
                 } else if(this.ins == 16) {
                   this.groupingItems()
+                } else if(this.ins == 17) {
+                  this.getAubprojectArr()
                 }
-                if(this.ins != 16) {
+                if(this.ins != 16 && this.ins != 17) {
                   this.getUserList()
                 }
             },
@@ -1580,6 +1596,11 @@ export default {
           sl.startDate = this.rangeDatas[0]
           sl.endDate = this.rangeDatas[1]
           sl.projectId = this.proJuctId
+        } else if(this.ins == 17) {
+          fName = '子项目工时成本表' + '.xls'
+          url += "/exportSubProjectTimeCost"
+          sl.startDate = this.rangeDatas[0]
+          sl.endDate = this.rangeDatas[1]
         }
           this.http.post(url, sl,
             res => {
@@ -1882,6 +1903,37 @@ export default {
             });
         });
     },
+    // 子项目工时成本表
+    getAubprojectArr() {
+      // this.total = 0
+      this.listLoading = true
+      this.http.post('/project/getSubProjectTimeCost', {
+         startDate: this.rangeDatas[0],
+         endDate: this.rangeDatas[1],
+         projectId: this.proJuctId,
+         pageIndex: this.page,
+         pageSize: this.size,
+      },
+        res => {
+            this.listLoading = false
+            if (res.code == "ok") {
+                this.subprojectArr = res.data.record
+                this.total = res.data.total
+            } else {
+                this.listLoading = false
+                this.$message({
+                  message: res.msg,
+                  type: "error"
+                });
+            }
+        },
+        error => {
+            this.$message({
+                message: error,
+                type: "error"
+            });
+        });
+    },
     overTime() {
       this.listLoading = true;
       var obj = {
@@ -2442,6 +2494,9 @@ export default {
       if(this.ins == 5) {
         this.getProjectStages()
       }
+      if(this.ins == 17) {
+        this.getAubprojectArr()
+      }
     },
     // 日期
     getCurrentRangeTime() {

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

@@ -645,7 +645,8 @@ import { error } from 'dingtalk-jsapi';
                 showImportResult:false,
                 widthHtval: document.body.clientWidth - 230,
                 deleteSelList: [],
-                chosenProjectsChecked: false
+                chosenProjectsChecked: false,
+                exportDataProcessing: false,
             };
         },
         methods: {
@@ -1319,7 +1320,7 @@ import { error } from 'dingtalk-jsapi';
                     }
                 },
                 error => {
-                    this.listLoading = false;
+                    this.exportDataProcessing = false;
                     this.$message({
                         message: error,
                         type: "error"

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

@@ -430,7 +430,7 @@
                             </el-option>
                         </el-select>
 
-                        <selectCat v-if="user.userNameNeedTranslate == 1" :size="'mini'" :subject="users" :subjectId="executorItem.executorId" :distinction="'1'" @selectCal="selectCal" :index="index" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !(groupResponsibleId == user.id)"></selectCat>
+                        <selectCat v-if="user.userNameNeedTranslate == 1" :size="'mini'" :filterable="true" :subject="users" :subjectId="executorItem.executorId" :distinction="'1'" @selectCal="selectCal" :index="index" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !(groupResponsibleId == user.id)"></selectCat>
                         <!-- <selectCat v-if="user.userNameNeedTranslate == '1'" :wxCope="true" :size="'size'" :subjectId="executorItem.executorId" :distinction="'1'" :subject="users"  @selectCal="selectCal" :index="index" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !(groupResponsibleId == user.id)"></selectCat> -->
 
 

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

@@ -255,7 +255,7 @@
                             </el-option>
                         </el-select>
                         
-                        <selectCat :subject="users" :subjectId="executorItem.executorId" :index="index" @selectCal="selectCal" :size="'mini'" v-if="user.userNameNeedTranslate == '1'"></selectCat>
+                        <selectCat :subject="users" :subjectId="executorItem.executorId" :filterable="true" :index="index" @selectCal="selectCal" :size="'mini'" v-if="user.userNameNeedTranslate == '1'"></selectCat>
 
                         <span style="margin-left:30px;margin-right:10px;">{{ $t('plantime') }}</span>
                         <el-input-number size="small" :disabled="(addForm.id != null && user.id != addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement" v-model="executorItem.planHours" style="width:30%;" :min="1" :max="100"  :placeholder="$t('pleaseentertheplannedworking')" ></el-input-number ><span style="margin-left:10px;">{{ $t('time.hour') }}</span>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 15585 - 555
fhKeeper/formulahousekeeper/timesheet_h5/package-lock.json


+ 2 - 0
fhKeeper/formulahousekeeper/timesheet_h5/package.json

@@ -17,6 +17,7 @@
     "css-loader": "^3.6.0",
     "dingtalk-jsapi": "^2.13.42",
     "echarts": "^4.9.0",
+    "font-awesome": "^4.7.0",
     "jquery": "^3.6.1",
     "style-loader": "^1.3.0",
     "vue": "^2.6.12",
@@ -38,6 +39,7 @@
     "postcss-loader": "^3.0.0",
     "postcss-pxtorem": "^4.0.1",
     "vant": "^2.12.18",
+    "vue-html5-editor": "^1.1.1",
     "vue-router": "^3.5.1",
     "vue-template-compiler": "^2.6.12",
     "vuex": "^3.6.2"

+ 109 - 0
fhKeeper/formulahousekeeper/timesheet_h5/src/main.js

@@ -45,6 +45,115 @@ Vue.config.productionTip = false;
 import * as echarts from 'echarts';
 Vue.prototype.$echarts = echarts;
 
+// 富文本
+import 'font-awesome/css/font-awesome.css' 
+import VueHtml5Editor from 'vue-html5-editor'
+Vue.use(VueHtml5Editor, {
+    name: "vue-html5-editor",
+    showModuleName: false,
+    icons: {
+        text: "fa fa-pencil",
+        color: "fa fa-paint-brush",
+        font: "fa fa-font",
+        align: "fa fa-align-justify",
+        list: "fa fa-list",
+        link: "fa fa-chain",
+        unlink: "fa fa-chain-broken",
+        tabulation: "fa fa-table",
+        image: "fa fa-file-image-o",
+        hr: "fa fa-minus",
+        eraser: "fa fa-eraser",
+        undo: "fa-undo fa",
+        "full-screen": "fa fa-arrows-alt",
+        info: "fa fa-info",
+    },
+    image: {
+        sizeLimit: 512 * 1024,
+        upload: {
+            url: null,
+            headers: {},
+            params: {},
+            fieldName: {}
+        },
+        compress: {
+            width: 1600,
+            height: 1600,
+            quality: 80
+        },
+        uploadHandler(responseText){
+            var json = JSON.parse(responseText)
+            if (!json.ok) {
+                alert(json.msg)
+            } else {
+                return json.data
+            }
+        }
+    },
+    language: "zh-cn",
+    i18n: {
+        "zh-cn": {
+            "align": "对齐方式",
+            "image": "图片",
+            "list": "列表",
+            "link": "链接",
+            "unlink": "去除链接",
+            "table": "表格",
+            "font": "文字",
+            "full screen": "全屏",
+            "text": "排版",
+            "eraser": "格式清除",
+            "info": "关于",
+            "color": "颜色",
+            "please enter a url": "请输入地址",
+            "create link": "创建链接",
+            "bold": "加粗",
+            "italic": "倾斜",
+            "underline": "下划线",
+            "strike through": "删除线",
+            "subscript": "上标",
+            "superscript": "下标",
+            "heading": "标题",
+            "font name": "字体",
+            "font size": "文字大小",
+            "left justify": "左对齐",
+            "center justify": "居中",
+            "right justify": "右对齐",
+            "ordered list": "有序列表",
+            "unordered list": "无序列表",
+            "fore color": "前景色",
+            "background color": "背景色",
+            "row count": "行数",
+            "column count": "列数",
+            "save": "确定",
+            "upload": "上传",
+            "progress": "进度",
+            "unknown": "未知",
+            "please wait": "请稍等",
+            "error": "错误",
+            "abort": "中断",
+            "reset": "重置"
+        }
+    },
+    hiddenModules: [],
+    visibleModules: [
+        "text",
+        "color",
+        "font",
+        "align",
+        "list",
+        "link",
+        "unlink",
+        "tabulation",
+        // "image",
+        "hr",
+        "eraser",
+        "undo",
+        "full-screen",
+        "info",
+    ],
+    modules: {}
+})
+
 new Vue({
     store,
     router,

+ 69 - 10
fhKeeper/formulahousekeeper/timesheet_h5/src/views/task/editask.vue

@@ -1,5 +1,5 @@
 <template>
-    <div>
+    <div class="editaskBox">
         <van-nav-bar :title="title" left-text="返回" @click-left="back" fixed left-arrow />
         <div class="content">
             <van-form>
@@ -70,12 +70,13 @@
                     <van-icon v-if="index != 0 && canEdit" class="delete_executor" name="delete-o" @click.stop="deleteExecutor(index)" />
                 </div>
                 <van-popup v-model="executor.show" position="bottom" v-if="canEdit">
-                    <van-search v-model="executor.searchText" placeholder="输入员工姓名搜索" @search="onSearch" v-if="user.userNameNeedTranslate != '1'"></van-search>
+                    <van-search v-model="executor.searchText" placeholder="输入员工姓名搜索" @input="onSearch"></van-search>
                     <div style="minHeight:300px;">
                         <van-radio-group v-model="executor.item">
                             <van-radio v-for="uitem in executor.searchList" :key="uitem.id" :name="uitem" style="padding:10px">
                                 <span v-if="user.userNameNeedTranslate != 1">{{uitem.name}}</span>
                                 <span v-else><ww-open-data type='userName' :openid='uitem.name'></ww-open-data></span>
+                                <span class="xinmingghao">{{uitem.jobNumber}}</span>
                             </van-radio>
                         </van-radio-group>
                     <van-button style="width:100%;position: -webkit-sticky;position: sticky;bottom: 0;" @click="searchExecutor()">确定</van-button>
@@ -95,10 +96,13 @@
                     @cancel="taskLevel.show = false;$forceUpdate();"/>
                 </van-popup>
 
+                <van-cell title="任务描述"/>
+                <vue-html5-editor :content="taskform.taskDesc" :height="300" @change="htmleditor"></vue-html5-editor>
+
             </van-form>
             <div class="form_btn" style="position:fixed; bottom:0px;width:100%;">
                 <div style="padding-bottom:10px;">
-                    <van-button square block type="info" @click="submitTask" native-type="submit" style="width:100%;float:left;" :disabled="!canEdit">
+                    <van-button square block type="info" loading-text="保存中..." @click="submitTask" native-type="submit" :loading="submitTaskBtn" style="width:100%;float:left;" :disabled="!canEdit">
                         <div v-if="canEdit">保存</div>
                         <div v-else>暂无权限编辑</div>
                     </van-button>
@@ -122,6 +126,7 @@ export default {
             minDate: new Date(2020,0,1),
             maxDate: new Date(2025,11,31),
             canEdit: true,
+            onSearchTime: null,
             taskform:{      // 表单
                 taskType: 0,
                 name: '',
@@ -139,6 +144,9 @@ export default {
             startDateShow: false,
             endDateShow: false,
             finishDateShow: false,
+
+            submitTaskBtn: false,
+
             taskLevel:{
                 show: false,
                 list: ['一般','重要','紧急']
@@ -169,6 +177,7 @@ export default {
                 startDate: null,
                 endDate: null,
                 finishDate: null,
+                taskDesc: '',
                 taskLevel: 0,
                 executorList: [{executorName: '',executorId: '',planHours: this.user.timeType.allday}]
             }
@@ -225,11 +234,39 @@ export default {
             this.$forceUpdate();
         },
         onSearch(val) {
-            console.log(val);
-            this.executor.searchList = [];
-            this.executor.list.forEach(u=>{if (u.name.startsWith(val)) {
-                this.executor.searchList.push(u);
-            }})
+            if(this.user.userNameNeedTranslate != 1) {
+                this.executor.searchList = [];
+                this.executor.list.forEach(u=>{if (u.name.startsWith(val)) {
+                    this.executor.searchList.push(u);
+                }})
+            } else {
+                if (this.onSearchTime != null) {
+                    clearTimeout(this.onSearchTime)
+                }
+                var that = this
+                this.onSearchTime = setTimeout(() => {
+                    that.getOnSearch(val)
+                }, 500)
+            }
+        },
+        getOnSearch(val) {
+            this.$axios.post("/user/getEmployeeList", {
+                departmentId: -1,
+                pageIndex: 1,
+                pageSize: 200,
+                keyword: val,
+                status: 1,
+                roleId: '',
+                cursor: '',
+                onlyDirect: 0,
+            })
+            .then(res => {
+                if(res.code == "ok") {
+                    this.executor.searchList = res.data.records
+                } else {
+                    this.$toast.fail('搜索失败');
+                }
+            }).catch(err=> {this.$toast.clear();console.log(err)});
         },
         searchExecutor(){
             this.taskform.executorList[this.executor.index].executorId = this.executor.item.id
@@ -269,18 +306,24 @@ export default {
             delete this.taskform.subTaskList;
             delete this.taskform.refTaskList;
             delete this.taskform.progress;
+            this.submitTaskBtn = true
+            // return
             this.$axios.post("/task/save", this.taskform)
             .then(res => {
+                this.submitTaskBtn = false
                 if(res.code == "ok") {
                     this.$toast.success('保存成功');
                     this.back()
                 } else {
                     this.$toast.fail('保存失败');
                 }
-            }).catch(err=> {this.$toast.clear();console.log(err)});
+            }).catch(err=> {this.$toast.clear();console.log(err);this.submitTaskBtn = false});
 
         },
-
+        htmleditor(e) {
+            this.taskform.taskDesc = e
+            console.log()
+        },
         getTask(){
             this.$axios.post("/task/getTask", {
                 id: this.taskId.id
@@ -290,6 +333,9 @@ export default {
                     this.taskform.createDate = null;
                     this.taskform.indate = null;
                     let projectManagement = false
+                    if(!this.taskform.taskDesc){
+                        this.taskform.taskDesc = ''
+                    }
                     if(this.taskform.startDate){
                         this.currentDate1 = new Date(this.taskform.startDate)
                     }
@@ -364,4 +410,17 @@ export default {
         color: #c03131;
     }
 }
+.xinmingghao {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    width: 200px;
+    display: inline-block;
+    float: right;
+}
+</style>
+<style>
+    .editaskBox .van-radio__label {
+        width: 100%;
+        display: inline-block;
+    }
 </style>

+ 12 - 2
fhKeeper/formulahousekeeper/timesheet_h5/src/views/task/index.vue

@@ -6,7 +6,7 @@
     <van-sticky offset-top="1.22667rem">
         <!-- 全部任务/我执行的/我创建的 -->
         <van-tabs v-model="active" @click="activeClick">
-            <van-tab title="全部任务" :name="0"></van-tab>
+            <van-tab title="全部任务" :name="0" v-if="viewAlltask"></van-tab>
             <van-tab title="我执行的" :name="1"></van-tab>
             <van-tab title="我创建的" :name="2"></van-tab>
         </van-tabs>
@@ -84,7 +84,9 @@
 export default {
     data() {
         return {
-            active: '0',
+            active: 1,
+            user: JSON.parse(localStorage.userInfo),
+            viewAlltask: false,
             select_state: '进行中',
             select_state_array: ['进行中','已完成'],
             select_state_show: false,
@@ -112,6 +114,14 @@ export default {
         }
     },
     mounted() {
+        for(let i in this.user.functionList){
+            if(this.user.functionList[i].name == '查看全部项目'){
+                this.viewAlltask = true
+            }
+            if(this.user.functionList[i].name == '管理全部项目'){
+                this.viewAlltask = true
+            }
+        }
         this.getList()
     },
     methods: {

+ 5 - 3
fhKeeper/formulahousekeeper/timesheet_h5/vue.config.js

@@ -4,9 +4,9 @@ const path = require('path');
 const themePath = path.resolve(__dirname,'src/assets/style/theme.less');
 const Timestamp = new Date().getTime();
 
-// var ip = '47.101.180.183'
+var ip = '47.101.180.183'
 // var ip = '192.168.2.7'
-var ip = '127.0.0.1'
+// var ip = '127.0.0.1'
 
 // var os = require('os'), ip = '', ifaces = os.networkInterfaces() // 获取本机ip
 // for (var i in ifaces) {
@@ -19,6 +19,8 @@ var ip = '127.0.0.1'
 // }
 
 module.exports = {
+    runtimeCompiler: true,
+
     // 关闭eslint检查
     lintOnSave: false,
     
@@ -45,7 +47,7 @@ module.exports = {
     configureWebpack: {
         externals: {
             axios: "axios" // 配置使用CDN
-        }
+        },
     },
 
     devServer: {