Преглед изворни кода

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

yurk пре 2 година
родитељ
комит
91b241005d
13 измењених фајлова са 645 додато и 13 уклоњено
  1. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/CompanyController.java
  2. 14 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  3. 34 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java
  4. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  5. 5 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  6. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserService.java
  7. 305 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  8. 15 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  9. 33 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  10. 4 0
      fhKeeper/formulahousekeeper/timesheet/src/permissions.js
  11. 66 3
      fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue
  12. 143 6
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  13. 1 0
      fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/CompanyController.java

@@ -12,6 +12,7 @@ import com.management.platform.service.ExpenseTypeService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
 import com.taobao.api.ApiException;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -227,5 +228,25 @@ public class CompanyController {
         return httpRespMsg;
     }
 
+    @RequestMapping("/editCompanyName")
+    public HttpRespMsg editCompanyName(String name,HttpServletRequest request){
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("token");
+        User user = userMapper.selectById(token);
+        if (StringUtils.isBlank(name)){
+            msg.setError("公司名称不可为空");
+            return msg;
+        }
+        if ("超级管理员".equals(user.getRoleName())){
+            Company company = companyMapper.selectById(user.getCompanyId());
+            company.setCompanyName(name);
+            companyMapper.updateById(company);
+            msg.msg = "修改成功";
+        }else {
+            msg.setError("无权修改");
+        }
+        return msg;
+    }
+
 }
 

+ 14 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -228,8 +228,8 @@ public class ProjectController {
      * 获取查询者所在公司每个项目的工时成本
      */
     @RequestMapping("/getTimeCost")
-    public HttpRespMsg getTimeCost(String startDate, String endDate, String userIds,Integer projectId) {
-        return projectService.getTimeCost(startDate, endDate, userIds,projectId, request);
+    public HttpRespMsg getTimeCost(String startDate, String endDate, String userIds,Integer projectId,Integer type) {
+        return projectService.getTimeCost(startDate, endDate, userIds,projectId,type, request);
     }
 
     /**
@@ -1219,5 +1219,17 @@ public class ProjectController {
     public HttpRespMsg nearProject(HttpServletRequest request){
         return projectService.nearProject(request);
     }
+
+    //FTE报表
+    @RequestMapping("/getFTEData")
+    public HttpRespMsg getFTEData(@RequestParam Integer pageIndex, @RequestParam Integer pageSize,String month,String area,HttpServletRequest request){
+        return projectService.getFTEData(pageIndex,pageSize,month,area,request);
+    }
+
+    //导出FTE报表
+    @RequestMapping("/exportFTEData")
+    public HttpRespMsg exportFTEData(String month,String area,HttpServletRequest request){
+        return projectService.exportFTEData(month,area,request);
+    }
 }
 

+ 34 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java

@@ -1,8 +1,11 @@
 package com.management.platform.controller;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.FeishuInfo;
 import com.management.platform.entity.User;
+import com.management.platform.entity.UserCustom;
+import com.management.platform.mapper.UserCustomMapper;
 import com.management.platform.service.FeishuInfoService;
 import com.management.platform.service.UserService;
 import com.management.platform.util.HttpRespMsg;
@@ -39,6 +42,9 @@ public class UserController {
     @Resource
     private FeishuInfoService feishuInfoService;
 
+    @Resource
+    private UserCustomMapper userCustomMapper;
+
     /**
      * 登录网页端
      * username 用户名
@@ -266,5 +272,33 @@ public class UserController {
         return httpRespMsg;
     }
 
+    /**
+     * 返回用户自定义的地区信息
+     * @return
+     */
+    @RequestMapping("/areaData")
+    public HttpRespMsg areaData(HttpServletRequest request){
+        String token = request.getHeader("token");
+        return userService.areaData(token);
+    }
+
+    /**
+     * 返回用户自定义的地区名称
+     * @return
+     */
+    @RequestMapping("/areaName")
+    public HttpRespMsg areaName(HttpServletRequest request){
+        HttpRespMsg httpRespMsg=new HttpRespMsg();
+        String token = request.getHeader("token");
+        User user = userService.getById(token);
+        List<UserCustom> userCustoms = userCustomMapper.selectList(new QueryWrapper<UserCustom>().eq("company_id", user.getCompanyId()).orderByAsc("id"));
+        String customName = "";
+        if (userCustoms.size() != 0){
+            customName = userCustoms.get(0).getName();
+        }
+        httpRespMsg.data = customName;
+        return httpRespMsg;
+    }
+
 }
 

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

@@ -153,4 +153,6 @@ public interface ProjectMapper extends BaseMapper<Project> {
     List<Map<String, Object>> getDegreeDetailCost(Integer companyId, String startDate, String endDate, Integer projectId,int curProjectId, List<Integer> finalDeptIds, List<Integer> filterDeptIds, List<Integer> deptIds);
 
     List<Project> selectNearProject(String userId);
+
+    List<Map<String, Object>> getFTEData(Integer companyId, String startDate, String endDate, Integer start, Integer size, String area, List<Integer> branchDepartment, List<Integer> deptIds);
 }

+ 5 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java

@@ -60,7 +60,7 @@ public interface ProjectService extends IService<Project> {
 
     HttpRespMsg deleteProject(Integer id, Integer force);
 
-    HttpRespMsg getTimeCost(String startDate, String endDate, String userIds,Integer projectId, HttpServletRequest request);
+    HttpRespMsg getTimeCost(String startDate, String endDate, String userIds,Integer projectId, Integer type,HttpServletRequest request);
 
     HttpRespMsg getProjectCost(String startDate, String endDate, Integer projectId,Integer stateKey, HttpServletRequest request);
 
@@ -238,4 +238,8 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg timeCostAndExpenseByProject(HttpServletRequest request, String startDate, String endDate, Integer projectId);
 
     HttpRespMsg nearProject(HttpServletRequest request);
+
+    HttpRespMsg getFTEData(Integer pageIndex, Integer pageSize, String month, String area, HttpServletRequest request);
+
+    HttpRespMsg exportFTEData(String month, String area, HttpServletRequest request);
 }

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

@@ -88,4 +88,6 @@ public interface UserService extends IService<User> {
     HttpRespMsg moveUserData(String sourceId, String targetId, HttpServletRequest request);
 
     ModelAndView loginByWXCode(String code, String state);
+
+    HttpRespMsg areaData(String token);
 }

+ 305 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.pagehelper.util.StringUtil;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.*;
 import com.management.platform.mapper.*;
@@ -47,6 +48,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.sql.Array;
 import java.sql.Timestamp;
 import java.text.DecimalFormat;
 import java.text.NumberFormat;
@@ -1103,7 +1105,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
 
     //获取查询者所在公司每个项目的工时成本
     @Override
-    public HttpRespMsg getTimeCost(String startDate, String endDate, String userIds,Integer projectId, HttpServletRequest request) {
+    public HttpRespMsg getTimeCost(String startDate, String endDate, String userIds,Integer projectId, Integer type,HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             //根据系统配置的员工成本计算方式,按固定时薪还是固定月薪,分情况计算。
@@ -1164,6 +1166,11 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 }
             }
 
+            if (type.equals(0)){
+                list = list.stream().sorted(Comparator.comparing(l -> -Double.parseDouble(l.get("costMoney").toString()))).collect(Collectors.toList());
+            }else {
+                list = list.stream().sorted(Comparator.comparing(l -> -Double.parseDouble(l.get("cost").toString()))).collect(Collectors.toList());
+            }
             resultMap.put("costList", list);
             resultMap.put("totalMoneyCost", totalMoneyCost);
             if(functionCostList.size()==0){
@@ -9691,4 +9698,301 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         httpRespMsg.data = projects;
         return httpRespMsg;
     }
+
+    //获取FTE报表数据
+    @Override
+    public HttpRespMsg getFTEData(Integer pageIndex, Integer pageSize, String month, String area, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg =new HttpRespMsg();
+        User targetUser = userMapper.selectById(request.getHeader("token"));
+        List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "全部部门FTE报表");
+        List<SysRichFunction> functionDeptList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "负责部门FTE报表");
+        List<Integer> deptIds=null;
+        List<Department> allDepartmentList=departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id",targetUser.getCompanyId()));
+        List<Department> userDepartmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("manager_id", targetUser.getId()).eq("company_id",targetUser.getCompanyId()));
+        List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("other_manager_id", targetUser.getId()));
+        //判断查看权限
+        if(functionAllList.size()==0){
+            deptIds=new ArrayList<>();
+            deptIds.add(-1);
+            if(functionDeptList.size()>0){
+                List<Integer> collect = userDepartmentList.stream().map(dm -> dm.getDepartmentId()).distinct().collect(Collectors.toList());
+                List<Integer> otherCollect = departmentOtherManagerList.stream().map(dom -> dom.getDepartmentId()).distinct().collect(Collectors.toList());
+                collect.addAll(otherCollect);
+                //将该用户管理的所有部门以及部门的子部门id添加到deptIds集合中
+                for (Integer integer : collect) {
+                    List<Integer> branchDepartment = getBranchDepartment(integer, allDepartmentList);
+                    deptIds.addAll(branchDepartment);
+                }
+            }
+        }
+        long total  = 0;
+        List<Map<String,Object>> resultList = null;
+        List<Integer> branchDepartment =null;
+        //若用户传入departmentId参数,则查询该部门所有子部门,添加到branchDepartment集合中
+//        if(departmentId!=null){
+//            branchDepartment = getBranchDepartment(departmentId, allDepartmentList);
+//        }
+        String startDate = null;
+        String endDate = null;
+        LocalDate time = LocalDate.parse(month, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        startDate = time.with(TemporalAdjusters.firstDayOfMonth()).toString();
+        endDate = time.with(TemporalAdjusters.lastDayOfMonth()).toString();
+        int days = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 0).size();
+        TimeType allDay = timeTypeMapper.selectOne(new QueryWrapper<TimeType>().eq("company_id", targetUser.getCompanyId()));
+        Float monthTime = days * allDay.getAllday();
+
+        if(pageIndex!=null&&pageSize!=null){
+            Integer size=pageSize;
+            Integer start=(pageIndex-1)*size;
+            resultList=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,start,size,area,branchDepartment,deptIds);
+            total=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,null,null,area,branchDepartment,deptIds).size();
+        }else{
+            resultList=projectMapper.getFTEData(targetUser.getCompanyId(),startDate,endDate,null,null,area,branchDepartment,deptIds);
+        }
+        for (Map<String, Object> map : resultList) {
+            map.put("FTE",Float.parseFloat(map.get("workTime").toString())/monthTime);
+        }
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", targetUser.getCompanyId()));
+        if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact().equals(1)){
+            for (Map<String, Object> map : resultList) {
+                map.put("userName",map.get("wxUserId"));
+                map.put("corpwx_userid","$userName=" + map.get("wxUserId") + "$");
+            }
+        }
+        HashMap<String, Object> map = new HashMap<>();
+        map.put("resultList",resultList);
+        map.put("total",total);
+        map.put("monthTime",monthTime);
+        httpRespMsg.data = map;
+        return httpRespMsg;
+    }
+
+    //导出FTE报表数据
+    @Override
+    public HttpRespMsg exportFTEData(String month, String area,HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+        List<UserCustom> userCustoms = userCustomMapper.selectList(new QueryWrapper<UserCustom>().eq("company_id", user.getCompanyId()).orderByAsc("id"));
+        String customName = "";
+        if (userCustoms.size() != 0){
+            customName = userCustoms.get(0).getName();
+        }
+        HttpRespMsg fteData = getFTEData(null, null, month, area, request);
+        Map<String, Object> data = (Map<String, Object>) (Map<String, Object>) fteData.data;
+        List<Map<String, Object>> resultList = (List<Map<String, Object>>) data.get("resultList");
+        Float monthTime = (Float) data.get("monthTime");
+        List<List<String>> dataList=new ArrayList<>();
+        List<String> titleList=new ArrayList<>();
+        List<String> subtitle=new ArrayList<>();
+        Integer no = 0;
+        titleList.add(customName);
+        titleList.add("序号");
+        titleList.add("CRC姓名");
+        titleList.add("项目号");
+        titleList.add("项目名称");
+        titleList.add("工时(H)");
+        titleList.add("FTE(工时/当月工时基数)");
+        titleList.add("非项目工时(H)(当月工时基数-项目工时合计工时数)");
+        dataList.add(titleList);
+        subtitle.add("");
+        subtitle.add("");
+        subtitle.add("");
+        subtitle.add("");
+        subtitle.add("");
+        subtitle.add("");
+        subtitle.add("当月工时:" + monthTime);
+        dataList.add(subtitle);
+        Float pTimeSum = 0.0F;
+        Float pFteSum = 0.0F;
+        Float aTimeSum = 0.0F;
+        Float aFteSum = 0.0F;
+        for (int i = 0; i < resultList.size(); i++) {
+            if (!resultList.get(i).containsKey("area")){
+                resultList.get(i).put("area","无");
+            }else if(org.apache.commons.lang3.StringUtils.isBlank(resultList.get(i).get("area").toString())){
+                resultList.get(i).put("area","无");
+            }
+            ArrayList<String> row = new ArrayList<>();
+            if (i == 0){
+                no += 1;
+                row.add(resultList.get(i).get("area").toString());
+                row.add(no + "");
+                if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact().equals(1)){
+                    row.add(resultList.get(i).get("corpwx_userid") + "");
+                }else {
+                    row.add(resultList.get(i).get("userName") + "");
+                }
+                row.add(resultList.get(i).get("projectCode") + "");
+                row.add(resultList.get(i).get("projectName") + "");
+
+                Float workTime = Float.valueOf(resultList.get(i).get("workTime").toString());
+                row.add(workTime + "");
+                pTimeSum += workTime;
+                aTimeSum += workTime;
+
+                Float FTE = Float.valueOf(resultList.get(i).get("workTime").toString()) / monthTime;
+                row.add(new BigDecimal(FTE).setScale(2, RoundingMode.HALF_UP) + "");
+                pFteSum += FTE;
+                aFteSum += FTE;
+
+                row.add("");
+
+                dataList.add(row);
+            }else if(resultList.get(i).get("area").equals(resultList.get(i - 1).get("area"))){
+                if (resultList.get(i).get("id").equals(resultList.get(i - 1).get("id"))){
+                    row.add("");
+                    row.add("");
+                    row.add("");
+                    row.add(resultList.get(i).get("projectCode") + "");
+                    row.add(resultList.get(i).get("projectName") + "");
+
+                    Float workTime = Float.valueOf(resultList.get(i).get("workTime").toString());
+                    row.add(workTime + "");
+                    pTimeSum += workTime;
+                    aTimeSum += workTime;
+
+                    Float FTE = Float.valueOf(resultList.get(i).get("workTime").toString()) / monthTime;
+                    row.add(new BigDecimal(FTE).setScale(2, RoundingMode.HALF_UP) + "");
+                    pFteSum += FTE;
+                    aFteSum += FTE;
+
+                    row.add("");
+
+                    dataList.add(row);
+                }else {
+                    ArrayList<String> sum = new ArrayList<>();
+                    sum.add("");
+                    sum.add("");
+                    sum.add("合计");
+                    sum.add("");
+                    sum.add("");
+                    sum.add(pTimeSum.toString());
+                    sum.add(new BigDecimal(pFteSum).setScale(2, RoundingMode.HALF_UP) + "");
+                    sum.add((monthTime - pTimeSum) + "");
+                    pTimeSum = 0.0F;
+                    pFteSum = 0.0F;
+                    dataList.add(sum);
+
+                    no += 1;
+                    row.add("");
+                    row.add(no + "");
+                    if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact().equals(1)){
+                        row.add(resultList.get(i).get("corpwx_userid") + "");
+                    }else {
+                        row.add(resultList.get(i).get("userName") + "");
+                    }
+                    row.add(resultList.get(i).get("projectCode") + "");
+                    row.add(resultList.get(i).get("projectName") + "");
+
+                    Float workTime = Float.valueOf(resultList.get(i).get("workTime").toString());
+                    row.add(workTime + "");
+                    pTimeSum += workTime;
+                    aTimeSum += workTime;
+
+                    Float FTE = Float.valueOf(resultList.get(i).get("workTime").toString()) / monthTime;
+                    row.add(new BigDecimal(FTE).setScale(2, RoundingMode.HALF_UP) + "");
+                    pFteSum += FTE;
+                    aFteSum += FTE;
+
+                    row.add("");
+
+                    dataList.add(row);
+                }
+
+            }else {
+                ArrayList<String> pSum = new ArrayList<>();
+                pSum.add("");
+                pSum.add("");
+                pSum.add("合计");
+                pSum.add("");
+                pSum.add("");
+                pSum.add(pTimeSum.toString());
+                pSum.add(new BigDecimal(pFteSum).setScale(2, RoundingMode.HALF_UP) + "");
+                pSum.add((monthTime - pTimeSum) + "");
+                pTimeSum = 0.0F;
+                pFteSum = 0.0F;
+
+                dataList.add(pSum);
+
+                ArrayList<String> sum = new ArrayList<>();
+                sum.add("");
+                sum.add("");
+                sum.add(customName + "合计");
+                sum.add("");
+                sum.add("");
+                sum.add(aTimeSum.toString());
+                //sum.add(new BigDecimal(aFteSum).setScale(2, RoundingMode.HALF_UP) + "");
+                sum.add("");
+                sum.add((monthTime - aTimeSum) + "");
+                pTimeSum = 0.0F;
+                pFteSum = 0.0F;
+                aTimeSum = 0.0F;
+                aFteSum = 0.0F;
+                dataList.add(sum);
+
+                ArrayList<String> n = new ArrayList<>();
+                n.add("");
+                dataList.add(n);
+
+                no += 1;
+                row.add(resultList.get(i).get("area")==null?"无":resultList.get(i).get("area").toString());
+                row.add(no + "");
+                if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact().equals(1)){
+                    row.add(resultList.get(i).get("corpwx_userid") + "");
+                }else {
+                    row.add(resultList.get(i).get("userName") + "");
+                }
+                row.add(resultList.get(i).get("projectCode") + "");
+                row.add(resultList.get(i).get("projectName") + "");
+
+                Float workTime = Float.valueOf(resultList.get(i).get("workTime").toString());
+                row.add(workTime + "");
+                pTimeSum += workTime;
+                aTimeSum += workTime;
+
+                Float FTE = Float.valueOf(resultList.get(i).get("workTime").toString()) / monthTime;
+                row.add(new BigDecimal(FTE).setScale(2, RoundingMode.HALF_UP) + "");
+                pFteSum += FTE;
+                aFteSum += FTE;
+
+                row.add("");
+
+                dataList.add(row);
+            }
+
+            if (i == resultList.size()-1){
+                ArrayList<String> pSum = new ArrayList<>();
+                pSum.add("");
+                pSum.add("");
+                pSum.add("合计");
+                pSum.add("");
+                pSum.add("");
+                pSum.add(pTimeSum.toString());
+                pSum.add(new BigDecimal(pFteSum).setScale(2, RoundingMode.HALF_UP) + "");
+                pSum.add((monthTime - pTimeSum) + "");
+                dataList.add(pSum);
+
+                ArrayList<String> sum = new ArrayList<>();
+                sum.add("");
+                sum.add("");
+                sum.add(customName + "合计");
+                sum.add("");
+                sum.add("");
+                sum.add(aTimeSum.toString());
+                //sum.add(new BigDecimal(aFteSum).setScale(2, RoundingMode.HALF_UP) + "");
+                sum.add("");
+                sum.add((monthTime - aTimeSum) + "");
+                dataList.add(sum);
+            }
+        }
+        String fileName = "FTE报表"+System.currentTimeMillis();
+        try {
+            return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName, dataList, path);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        httpRespMsg.data =  pathPrefix + fileName+".xlsx";
+        return httpRespMsg;
+    }
 }

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

@@ -2840,4 +2840,19 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
             return null;
         }
     }
+
+    @Override
+    public HttpRespMsg areaData(String token) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        User user = userMapper.selectById(token);
+        List<User> items = userMapper.selectList(new QueryWrapper<User>().select("DISTINCT plate1").eq("company_id", user.getCompanyId()));
+        ArrayList<String> areas = new ArrayList<String>();
+        for (User item : items) {
+            if (item!= null && item.getPlate1()!= null && org.apache.commons.lang3.StringUtils.isNotBlank(item.getPlate1())){
+                areas.add(item.getPlate1());
+            }
+        }
+        httpRespMsg.data = areas;
+        return httpRespMsg;
+    }
 }

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

@@ -1600,4 +1600,37 @@
             ) p2
         )
     </select>
+
+    <select id="getFTEData" resultType="java.util.Map">
+        SELECT u.id,u.name userName,u.corpwx_userid wxUserId,u.plate1 area,SUM(r.working_time) workTime,p.project_name projectName,p.project_code projectCode
+        FROM `user` u
+        LEFT JOIN report r
+        ON u.id = r.creator_id
+        LEFT JOIN project p
+        ON r.project_id = p.id
+        WHERE r.state = 1
+        AND p.is_public = 0
+        AND u.company_id=#{companyId}
+        AND r.create_date BETWEEN #{startDate} AND #{endDate}
+        <if test="area!=null and area != '' ">
+            and u.plate1 = #{area}
+        </if>
+        <if test="branchDepartment!=null and branchDepartment.size()>0">
+            and us.department_id in
+            <foreach collection="branchDepartment" open="(" close=")" separator="," item="item">
+                #{item}
+            </foreach>
+        </if>
+        <if test="deptIds!=null and deptIds.size()>0">
+            and us.department_id in
+            <foreach collection="deptIds" open="(" item="item" close=")" separator=",">
+                #{item}
+            </foreach>
+        </if>
+        GROUP BY u.id,p.id,u.plate1,p.project_name,u.name,u.corpwx_userid,p.project_code
+        order by area,id
+        <if test="start!=null and size!=null">
+            limit #{start},#{size}
+        </if>
+    </select>
 </mapper>

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

@@ -90,6 +90,8 @@ const StringUtil = {
         reportStageWorkingTime: false, // 负责项目分组阶段工时 //
         reportAllManhourCost: false, // 全部子项目工时成本 //
         reportResponsibleManhourCost: false, // 负责项目子项目工时成本 //
+        reportFTEAll: false, // 全部部门FTE报表 //
+        reportFTEPart: false, // 负责部门FTE报表 // 
 
         // 请假模块
         leaveFil : false, // 请假填报 // 
@@ -218,6 +220,8 @@ const StringUtil = {
         arr[i] == '编辑负责项目编码和名称' ? obj.projectCodeAndName = true : ''
         arr[i] == '全部分组阶段工时' ? obj.reportPhaseHours = true : ''
         arr[i] == '负责项目分组阶段工时' ? obj.reportStageWorkingTime = true : ''
+        arr[i] == '全部部门FTE报表' ? obj.reportFTEAll = true : ''
+        arr[i] == '负责部门FTE报表' ? obj.reportFTEPart = true : ''
 
         arr[i] == '新增合同' ? obj.contractNew = true : ''
         arr[i] == '查看全部合同' ? obj.contractView = true : ''

+ 66 - 3
fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue

@@ -12,11 +12,12 @@
                 </div>
             </el-col>
             <el-col :span="6">
-                <div class="tools" @click.prevent="collapse" style="position: relative;">
-                    <i class="fa fa-align-justify"></i>
+                <div class="tools"  style="position: relative;">
+                    <i class="fa fa-align-justify" @click.prevent="collapse" style="position: relative;z-index: 10;"></i>
                     <div class="gongshimingz">
                         {{user.companyName}}
-                    </div>
+                        <i v-if="user.roleName == '超级管理员'" class="el-icon-edit" @click="editCompanyNamedialog=true,companyForm.name = user.companyName"  style="position: relative;z-index: 15; margin-left: 5px;"></i>
+                    </div>                    
                 </div>
             </el-col>
 
@@ -230,6 +231,21 @@
                         <el-button type="primary" @click.native="editInfo" :loading="editLoading2">{{$t('btn.submit')}}</el-button>
                     </div>
                 </el-dialog>
+
+                <el-dialog
+                    title="修改公司名称"
+                    :visible.sync="editCompanyNamedialog"
+                    width="30%">
+                    <el-form :model="companyForm" :rules="rules" ref="companyForm" label-width="100px" class="demo-ruleForm">
+                        <el-form-item label="公司名称" prop="name">
+                            <el-input v-model.trim="companyForm.name"></el-input>
+                        </el-form-item>
+                    </el-form>
+                    <span slot="footer" class="dialog-footer">
+                        <el-button @click="editCompanyNamedialog = false">取 消</el-button>
+                        <el-button type="primary" @click="editCompanyName('companyForm')">确 定</el-button>
+                    </span>
+                </el-dialog>
             </section>
         </el-col>
     </el-row>
@@ -242,7 +258,17 @@
         inject:['reloads'],
         data() {
             return {
+                companyForm:{
+                    name: '',
+                },
+                rules: {
+                    name: [
+                        { required: true, message: '请输入公司名称', trigger: 'blur' },
+                        { min: 1, max: 20, message: '长度为1-20个字符', trigger: 'blur' }
+                    ]
+                },
                 tourFlg: false,
+                editCompanyNamedialog:false,
                 firstTourFalse: localStorage.getItem('firstTourFalse') | true, // 是否需要新手指导
                 steps: [
                     {
@@ -490,6 +516,43 @@
                 });
             },
 
+            
+            //编辑公司名称
+            editCompanyName(companyForm){
+                this.$refs[companyForm].validate((valid) => {
+                    if (valid) {
+                        this.http.post("/company/editCompanyName", {name:this.companyForm.name},
+                            res => {
+                            if (res.code == "ok") {
+                                this.editCompanyNamedialog = false;
+                                let list = JSON.parse(sessionStorage.getItem("user") || '[]')
+                                sessionStorage.removeItem('user')
+                                this.user.companyName = this.companyForm.name
+                                list.companyName = this.companyForm.name
+                                sessionStorage.setItem("user",JSON.stringify(list))
+                                this.$message({
+                                message: res.msg,
+                                type: "success"
+                                });
+                            } else {
+                                this.$message({
+                                message: res.msg,
+                                type: "error"
+                                });
+                            }
+                            },
+                            error => {
+                            this.$message({
+                                message: error,
+                                type: "error"
+                            });
+                        });
+                    } else {
+                        return false;
+                    }
+                });
+            },
+
             reset() {
                 this.editPassWord = true;
                 this.addForm.id = JSON.parse(sessionStorage.getItem("user")).id;

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

@@ -39,6 +39,7 @@
                   <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-19" v-if="user.timeType.restartTaskNeedReason == 1" @click="ssl(18)"><p>任务重启表</p></el-menu-item>
+                  <el-menu-item index="1-20" v-if="permissions.reportFTEAll || permissions.reportFTEPart" @click="ssl(19)"><p>FTE报表</p></el-menu-item>
                   <!-- <el-menu-item index="1-12"><p @click="ssl(11)">人员工时统计表</p></el-menu-item> -->
                 </el-submenu>
               </el-menu>
@@ -87,14 +88,14 @@
           <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 && ins != 17" 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 != 19 && 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>
           </el-option>
         </el-select>
         <!-- 月份选择 -->
-        <el-date-picker v-if="ins == 14 || ins == 15" value-format="yyyy-MM" v-model="monthPersonnel" type="month" :placeholder="$t('Selectmonth')" :clearable="false" @change="selcts()" size="small"></el-date-picker>
+        <el-date-picker v-if="ins == 14 || ins == 15 || ins == 19" value-format="yyyy-MM" v-model="monthPersonnel" type="month" :placeholder="$t('Selectmonth')" :clearable="false" @change="selcts()" size="small"></el-date-picker>
           
           <!-- 部门筛选 -->
           <el-cascader v-if="(ins == 15 || (ins == 9 && permissions.reportAllTimely) || (ins == 8 && permissions.reportAllTimeDivide) || (ins == 6 && permissions.reportAllOvertime) || (ins == 11 && permissions.reportPersonnel) || (ins == 14)) && user.userNameNeedTranslate != 1" v-model="departmentIdArray" :options="departmentList" :placeholder="$t('qing-xuan-ze-bu-men')"
@@ -118,6 +119,11 @@
             <el-option :label="$t('state.yes')" value="1"></el-option>
           </el-select>
 
+          <!-- 地区筛选 -->
+          <el-select v-if="ins == 19" v-model="areaName" :placeholder="customNameChoose" @change="selcts()" clearable filterable size="small" style="margin-left:10px;width:150px">
+            <el-option :label="item" :value="item" v-for="item,index in areaList" :key="index"></el-option>
+          </el-select>
+
           <!-- 人员筛选 -->
           <el-select v-if="(ins == 6 || ins == 8 || ins == 9 || ins == 10 || ins == 11 || ins == 14 || ins == 18)  && user.userNameNeedTranslate != '1'" v-model="userId" :placeholder="$t('pleaseselectpersonnel')" @change="selcts()" clearable filterable size="small" style="margin-left:10px;width:150px">
             <el-option v-for="(item, index) in selUserList" :key="index" :label="item.name" :value="item.id"></el-option>
@@ -833,6 +839,27 @@
                 <el-table-column align="center" prop="restartDate" label="重启时间" min-width="150"></el-table-column>
             </el-table>
 
+            <!-- ETF报表 -->
+            <el-table v-if="ins == 19"  key="19" border :data="fTEDataList" highlight-current-row v-loading="listLoading" :height="+tableHeight - 1" style="width: 100%;">
+                <el-table-column align="center" prop="area" :label="customName" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="projectCode" label="项目编号" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="projectName" label="项目名称" min-width="250"></el-table-column>
+                <el-table-column align="center" prop="userName" label="人名" min-width="150">
+                  <template slot-scope="scope">
+                    <div>
+                      <span v-if="user.userNameNeedTranslate == '1'">
+                        <ww-open-data type='userName' :openid='scope.row.userName'></ww-open-data>
+                      </span>
+                      <span v-if="user.userNameNeedTranslate != '1'">
+                        {{scope.row.userName}}
+                      </span>
+                    </div>
+                  </template>
+                </el-table-column>
+                <el-table-column align="center" prop="workTime" label="工时" min-width="150"></el-table-column>
+                <el-table-column align="center" prop="FTE" label="FTE(工时/当月工时基数)" min-width="250"></el-table-column>
+            </el-table>
+
         <!--工具条-->
         <el-col :span="24" class="toolbar" v-if="ins != 6">
           <el-pagination
@@ -1059,6 +1086,9 @@ export default {
   props: {},
   data() {
     return {
+      customNameChoose: '',
+      areaName: '',
+      customName: '',
       permissions: JSON.parse(sessionStorage.getItem("permissions")),
       curProject:{},
       feeType:[this.$t('generalcost'), this.$t('travelexpenses'), this.$t('outsourcingcost')],
@@ -1106,13 +1136,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'), '子项目工时成本表', '任务重启表', 'FTE报表'],
 
       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'), '子项目工时成本表', '任务重启表', 'FTE报表'],
 
       ins: 10000,
       user: JSON.parse(sessionStorage.user),
@@ -1179,6 +1209,7 @@ export default {
       subprojectArr: [],
 
       taskRestartArr: [], // 任务重启表数据
+      fTEDataList: [], // FTE数据
     };
   },
   computed: {},
@@ -1269,6 +1300,7 @@ export default {
       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}
       if(this.user.timeType.restartTaskNeedReason == 1) {this.ssl(18);this.defaultActive = '1-19';return}
+      if(this.permissions.reportFTEAll || this.permissions.reportFTEPart) {this.ssl(19);this.defaultActive = '1-20';return}
       {this.allWrong = false}
     },
     rowspan(spanArr,position,spanName){
@@ -1306,7 +1338,26 @@ export default {
       }
     },
 
-
+    getCustomName(){
+      this.http.post('/user/areaName', {},
+      res => {
+          if (res.code == "ok") {
+              this.customName = res.data
+              this.customNameChoose = "请选择" + res.data
+          } else {
+              this.$message({
+                message: res.msg,
+                type: "error"
+              });
+          }
+      },
+      error => {
+          this.$message({
+              message: error,
+              type: "error"
+          });
+      });
+    },
 
     getUserList() {
       console.log(this.shuzArr[this.ins])
@@ -1514,8 +1565,11 @@ export default {
                   this.getAubprojectArr()
                 } else if(this.ins == 18) {
                   this.taskRestart()
+                } else if(this.ins == 19) {
+                  this.getETF()
+                  this.getArea()
                 }
-                if(this.ins != 16 && this.ins != 17 && this.ins != 18) {
+                if(this.ins != 16 && this.ins != 17 && this.ins != 18 && this.ins != 19) {
                   this.getUserList()
                 }
             },
@@ -1642,6 +1696,11 @@ export default {
           sl.endDate = this.rangeDatas[1]
           sl.projectId = this.proJuctId
           sl.personLiableId = this.userId
+        } else if(this.ins == 19) {
+          fName = 'FTE报表' + '.xlsx'
+          url += "/exportFTEData"
+          sl.month = this.monthPersonnel + '-01'
+          sl.area = this.areaName || null
         }
           this.http.post(url, sl,
             res => {
@@ -1729,6 +1788,84 @@ export default {
       this.page = 1
       this.getAuditRateList()
     },
+    // 获取EFT报表的数据
+    getETF() {
+      this.getCustomName();
+      this.listLoading = true;
+      let parameter = {
+        month: this.monthPersonnel + '-01',
+        area: this.areaName || null,
+        pageIndex: this.page,
+        pageSize: this.size
+      }
+      this.http.post('/project/getFTEData', parameter,
+      res => {
+          if (res.code == "ok") {
+              for (var i in res.data.resultList) {
+                res.data.resultList[i].FTE = res.data.resultList[i].FTE.toFixed(2)
+              }
+              this.fTEDataList = res.data.resultList;
+              this.total = res.data.total;
+              this.listLoading = false; 
+          } else {
+              this.$message({
+              message: res.msg,
+              type: "error"
+              });
+          }
+      },
+      error => {
+          this.$message({
+              message: error,
+              type: "error"
+          });
+      });
+    },
+    getArea() {
+      this.http.post('/user/areaData', {},
+      res => {
+          if (res.code == "ok") {
+             this.areaList = res.data
+          } else {
+              this.$message({
+              message: res.msg,
+              type: "error"
+              });
+          }
+      },
+      error => {
+          this.$message({
+              message: error,
+              type: "error"
+          });
+      });
+    },
+    getETFSummaries() {
+      const { columns, data } = param;
+        const sums = [];
+        columns.forEach((column, index) => {
+          if (index === 0) {
+            sums[index] = '总工时';
+            return;
+          }
+          const values = data.map(item => Number(item[column.property]));
+          if (!values.every(value => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => {
+              const value = Number(curr);
+              if (!isNaN(value)) {
+                return prev + curr;
+              } else {
+                return prev;
+              }
+            }, 0);
+            sums[index] += ' h';
+          } else {
+            sums[index] = '/';
+          }
+        });
+
+        return sums;
+    },
     // 获取人员工时统计表
     getPersonnelList() {
       let parameter = {

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

@@ -847,6 +847,7 @@
                 if (this.radio==this.$t('other.project')) {
                     url = this.port.project.listCost;
                     param.projectId=this.proJuctId
+                    param.type=this.yAxisValue
                 }else if(this.radio == this.$t('zhu-xiang-mu')){
                     url = '/project/getTimeCostByMainProject'
                     // param.userId = this.user.id