Browse Source

Merge branch 'master' of http://39.98.153.250:9080/bowintek/EmploymentSite

 Conflicts:
	src/main/java/com/hz/employmentsite/controller/AccountController.java
82064491C07A712AE32B5B57EC6EF136 3 months ago
parent
commit
ebd832229a
27 changed files with 1241 additions and 40 deletions
  1. 4 0
      doc/待更新脚本.txt
  2. 41 7
      src/main/java/com/hz/employmentsite/controller/AccountController.java
  3. 6 0
      src/main/java/com/hz/employmentsite/controller/companyService/CompanyController.java
  4. 23 0
      src/main/java/com/hz/employmentsite/controller/statistics/StatisticsController.java
  5. 3 0
      src/main/java/com/hz/employmentsite/mapper/cquery/CompanyCQuery.java
  6. 30 0
      src/main/java/com/hz/employmentsite/mapper/cquery/StatisticsCQuery.java
  7. 6 0
      src/main/java/com/hz/employmentsite/services/impl/companyService/CompanyServiceImpl.java
  8. 14 10
      src/main/java/com/hz/employmentsite/services/impl/jobUserManager/JobUserServiceImpl.java
  9. 33 0
      src/main/java/com/hz/employmentsite/services/impl/statistics/StatisticsServiceImpl.java
  10. 3 0
      src/main/java/com/hz/employmentsite/services/service/companyService/CompanyService.java
  11. 15 0
      src/main/java/com/hz/employmentsite/services/service/statistics/StatisticsService.java
  12. 109 0
      src/main/java/com/hz/employmentsite/util/RedisClient.java
  13. 126 0
      src/main/java/com/hz/employmentsite/vo/companyService/AllCompanyVo.java
  14. 10 0
      src/main/java/com/hz/employmentsite/vo/statistics/company/ModelCompanyCount.java
  15. 6 0
      src/main/resources/mapping/cquery/CompanyCQuery.xml
  16. 196 0
      src/main/resources/mapping/cquery/StatisticsCQuery.xml
  17. 13 0
      vue/src/api/companyService/company.ts
  18. 1 0
      vue/src/api/login/index.ts
  19. 48 0
      vue/src/api/statistics/index.ts
  20. 1 0
      vue/src/router/asyncModules/statistics.ts
  21. 13 5
      vue/src/store/modules/user.ts
  22. 5 0
      vue/src/utils/request.ts
  23. 4 3
      vue/src/views/jobUserManager/jobhunt/edit.vue
  24. 8 5
      vue/src/views/jobUserManager/jobhunt/recommend.vue
  25. 32 8
      vue/src/views/login/index.vue
  26. 489 0
      vue/src/views/statistics/CompanyStatistics.vue
  27. 2 2
      vue/src/views/statistics/SiteStatistics.vue

+ 4 - 0
doc/待更新脚本.txt

@@ -1,3 +1,7 @@
 INSERT INTO sys_function_code VALUES ('T010506', '驿站统计报表', 'T0105', 6);
 INSERT INTO `sys_menu` VALUES ('T010506', 6, '驿站统计报表', NULL, 'views/statistics/SiteStatistics', '/siteStatistics', 'T0105', NULL, 0, 1, 1, 'T010506', 1, NULL, NULL);
 insert into sys_role_sys_function_code (`RoleID`, `FunctionCode`) values('20afde90-a81a-11ed-a6c5-7085c2a9999e','T010506');
+
+INSERT INTO sys_function_code VALUES ('T010507', '企业统计报表', 'T0105', 7);
+INSERT INTO `sys_menu` VALUES ('T010507', 7, '企业统计报表', NULL, 'views/statistics/CompanyStatistics', '/companyStatistics', 'T0105', NULL, 0, 1, 1, 'T010507', 1, NULL, NULL);
+insert into sys_role_sys_function_code (`RoleID`, `FunctionCode`) values('20afde90-a81a-11ed-a6c5-7085c2a9999e','T010507');

+ 41 - 7
src/main/java/com/hz/employmentsite/controller/AccountController.java

@@ -7,10 +7,7 @@ import com.hz.employmentsite.filter.exception.RespGenerstor;
 import com.hz.employmentsite.services.service.AccountService;
 import com.hz.employmentsite.services.service.UserService;
 import com.hz.employmentsite.services.service.system.LogService;
-import com.hz.employmentsite.util.DateUtils;
-import com.hz.employmentsite.util.DesUtils;
-import com.hz.employmentsite.util.JsonMapper;
-import com.hz.employmentsite.util.TokenUtils;
+import com.hz.employmentsite.util.*;
 import com.hz.employmentsite.util.ip.IpUtils;
 import com.hz.employmentsite.vo.DesModel;
 import com.hz.employmentsite.vo.MenuData;
@@ -43,6 +40,8 @@ public class AccountController {
     private UserService userService;
     @Autowired
     private LogService logService;
+    @Autowired
+    private RedisClient redisClient;
 
     private Integer[] appLoginUserType = {3};
 
@@ -65,13 +64,48 @@ public class AccountController {
         String[] desData = desUtils.decoder(model.getToken(), dateUtils.DateToDateTime(dateUtils.StrToDate(model.getTm(), "yyyy/MM/dd HH:mm:ss"))).split("\\|");
 
         //使用时间*
-        if (new Date().compareTo(dateUtils.strToDateExt("2024-12-27")) >= 0) {
+        if (new Date().compareTo(dateUtils.strToDateExt("2024-11-26")) >= 0) {
             throw new Exception("java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String");
         }
+
+        // 账号锁定检查
+        Object isLock = redisClient.get("login_lock:" + desData[0]);
+        if (isLock != null) {
+            // 获取失效时间(秒)
+            long expire = redisClient.getExpire("login_lock:" + desData[0]);
+            // 将剩余时间格式化为分钟和秒
+            long minutes = expire / 60;
+            long seconds = expire % 60;
+            // 根据expire修改自定义异常的报错信息
+            String message = String.format("当前账号因账号密码输入错误次数过多,已被锁定,请等待%d分%d秒后重试", minutes, seconds);
+            throw new BaseException("20001", message);
+        }
+
+
+        // 按用户名和密码匹配用户
         UserModel user = accountService.verifyUser(desData[0], desData[1]);
 
-        if (user == null)
-            throw new BaseException(BaseErrorEnum.USER_PASSWORD_ERROR);
+        // 未匹配成功,进行错误次数记录
+        if (user == null) {
+            String loginErrorKey = "login_error:" + desData[0];
+            String loginLockKey = "login_lock:" + desData[0];
+            // 获取当前账号的错误次数
+            Object loginErrorNum = redisClient.get(loginErrorKey);
+            int num = (loginErrorNum == null) ? 0 : (int) loginErrorNum;
+            // 判断是否达到锁定条件
+            if (num >= 4) {
+                // 锁定账号,设置30分钟锁定时间
+                redisClient.set(loginLockKey, true, 1800);
+                redisClient.delete(loginErrorKey);
+                throw new BaseException("20001", "当前账号因账号密码输入错误次数过多,已被锁定,请等待30分钟后重试");
+            }
+            // 增加错误次数
+            redisClient.set(loginErrorKey, ++num, 300);
+            throw new BaseException("20002", "账号密码输入错误,已错误" + num + "次,错误5次之后将锁定账号");
+        }
+
+        // 登录成功清除账号错误次数
+        redisClient.delete("login_error:" + desData[0]);
 
         user.token = TokenUtils.sign(user.getUserId() + '|' + user.getUserTypeId());
         user.dataRangeList = userService.getUserDataRange(user.getUserId());

+ 6 - 0
src/main/java/com/hz/employmentsite/controller/companyService/CompanyController.java

@@ -67,6 +67,12 @@ public class CompanyController {
         return RespGenerstor.success(result);
     }
 
+    @ResponseBody
+    @GetMapping("/getAllList")
+    public BaseResponse<PageInfo<CompanyVo>> getAllList() {
+        return RespGenerstor.success(companyService.getAllList());
+    }
+
     @ResponseBody
     @GetMapping("/getFirmNameLikeList")
     public BaseResponse<PageInfo<PcFirm>> getFirmNameLikeList(@RequestParam("pageIndex") int pageIndex, @RequestParam("pageSize") int pageSize,

+ 23 - 0
src/main/java/com/hz/employmentsite/controller/statistics/StatisticsController.java

@@ -236,6 +236,29 @@ public class StatisticsController {
         return RespGenerstor.success(statisticsService.findPersonTypeCountInJobUserData(keyPersonTypeID, startDate, endDate, regionCode, siteID));
     }
 
+    /**
+     * 查询各区县的各个规模的企业数量与走访企业次数
+     */
+    @GetMapping("/companyModelCompanyCountInRegion")
+    public BaseResponse getRegionCompanyModelCompanyCount(@RequestParam(required = false) Date startDate, @RequestParam(required = false) Date endDate) {
+        return RespGenerstor.success(statisticsService.findRegionCompanyModelCompanyCount(startDate, endDate));
+    }
+
+    /**
+     * 查询各区县的各个规模的企业用工人数与岗位招聘人数
+     */
+    @GetMapping("/workSituationCountInRegion")
+    public BaseResponse getRegionCompanyWorkSituationCount(@RequestParam(required = false) Date startDate, @RequestParam(required = false) Date endDate) {
+        return RespGenerstor.success(statisticsService.findRegionCompanyWorkSituationCount(startDate, endDate));
+    }
+
+    /**
+     * 查询各个行业各个规模的企业的岗位招聘人数情况
+     */
+    @GetMapping("/workSituationCountInIndustry")
+    public BaseResponse getIndustryCompanyWorkSituationCount(@RequestParam(required = false) Date startDate, @RequestParam(required = false) Date endDate) {
+        return RespGenerstor.success(statisticsService.findIndustryCompanyWorkSituationCount(startDate, endDate));
+    }
 
     /**
      * 导出指定时间段的系统使用情况

+ 3 - 0
src/main/java/com/hz/employmentsite/mapper/cquery/CompanyCQuery.java

@@ -1,6 +1,7 @@
 package com.hz.employmentsite.mapper.cquery;
 
 import com.hz.employmentsite.model.PcFirm;
+import com.hz.employmentsite.vo.companyService.AllCompanyVo;
 import com.hz.employmentsite.vo.companyService.CompanyVo;
 import com.hz.employmentsite.vo.dataMap.CompanyPostMapVo;
 import com.hz.employmentsite.vo.signin.SigninVo;
@@ -20,6 +21,8 @@ public interface CompanyCQuery {
                             @Param("industryID") String industryID, @Param("isAllCompany") boolean isAllCompany,
                             @Param("createUserName") String createUserName);
 
+    List<AllCompanyVo> getAllList();
+
     List<PcFirm> getFirmNameLikeList(@Param("firmName") String firmName);
 
     /**

+ 30 - 0
src/main/java/com/hz/employmentsite/mapper/cquery/StatisticsCQuery.java

@@ -213,4 +213,34 @@ public interface StatisticsCQuery {
     List<PersonTypeJobUserCount> findPersonTypeCountInCultureRank(@Param("keyPersonTypeID") Integer keyPersonTypeID, @Param("startDate") Date startDate,
                                                                @Param("endDate") Date endDate, @Param("regionCode") String regionCode,
                                                                @Param("siteID") String siteID);
+
+    /**
+     * 查询各区县额企业的企业规模分布情况
+     */
+    List<ModelCompanyCount> findRegionCompanyModelCompanyCount(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
+
+    /**
+     * 查询各区县各个规模的企业走访情况
+     */
+    List<ModelCompanyCount> findRegionCompanyModelSigninCompanyCount(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
+
+    /**
+     * 查询各区县各个规模的企业的用工情况
+     */
+    List<ModelCompanyCount> findRegionCompanyWorkSituationCount(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
+
+    /**
+     * 查询各区县各个规模的企业的岗位招聘人数情况
+     */
+    List<ModelCompanyCount> findRegionCompanyRecruitCount(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
+
+    /**
+     * 查询各个行业各个规模的企业的用工情况
+     */
+    List<ModelCompanyCount> findIndustryCompanyWorkSituationCount(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
+
+    /**
+     * 查询各个行业各个规模的企业的岗位招聘人数情况
+     */
+    List<ModelCompanyCount> findIndustryCompanyRecruitCount(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
 }

+ 6 - 0
src/main/java/com/hz/employmentsite/services/impl/companyService/CompanyServiceImpl.java

@@ -17,6 +17,7 @@ import com.hz.employmentsite.util.RegexUtils;
 import com.hz.employmentsite.util.StringUtils;
 import com.hz.employmentsite.util.ip.IpUtils;
 import com.hz.employmentsite.vo.baseSettings.LabelVo;
+import com.hz.employmentsite.vo.companyService.AllCompanyVo;
 import com.hz.employmentsite.vo.companyService.AppCompanyPostVo;
 import com.hz.employmentsite.vo.companyService.CompanyVo;
 import com.hz.employmentsite.vo.companyService.PostVo;
@@ -116,6 +117,11 @@ public class CompanyServiceImpl implements CompanyService {
         return result;
     }
 
+    @Override
+    public List<AllCompanyVo> getAllList() {
+        return companyCQuery.getAllList();
+    }
+
     @Override
     public PageInfo<PcFirm> getFirmNameLikeList(Integer pageIndex, Integer pageSize, String firmName) {
 //        PageHelper.startPage(pageIndex, pageSize);

+ 14 - 10
src/main/java/com/hz/employmentsite/services/impl/jobUserManager/JobUserServiceImpl.java

@@ -704,18 +704,22 @@ public class JobUserServiceImpl implements JobUserService {
         dataList.forEach(item->{
             var curIdentityNumber = item.getIdentityNumber();
             var curUserMobile = item.getUserMobile();
-            if(!allIdentityList.contains(curIdentityNumber)){
-                allIdentityList.add(curIdentityNumber);
-            }else{
-                if(!repeatIdentityList.contains(curIdentityNumber)){
-                    repeatIdentityList.add(curIdentityNumber);
+            if (!stringUtils.IsNullOrEmpty(item.getIdentityNumber())){
+                if(!allIdentityList.contains(curIdentityNumber)){
+                    allIdentityList.add(curIdentityNumber);
+                }else{
+                    if(!repeatIdentityList.contains(curIdentityNumber)){
+                        repeatIdentityList.add(curIdentityNumber);
+                    }
                 }
             }
-            if(!allPhoneList.contains(curUserMobile)){
-                allPhoneList.add(curUserMobile);
-            }else{
-                if(!repeatUserMobileList.contains(curUserMobile)){
-                    repeatUserMobileList.add(curUserMobile);
+            if (!stringUtils.IsNullOrEmpty(item.getUserMobile())) {
+                if(!allPhoneList.contains(curUserMobile)){
+                    allPhoneList.add(curUserMobile);
+                }else{
+                    if(!repeatUserMobileList.contains(curUserMobile)){
+                        repeatUserMobileList.add(curUserMobile);
+                    }
                 }
             }
         });

+ 33 - 0
src/main/java/com/hz/employmentsite/services/impl/statistics/StatisticsServiceImpl.java

@@ -643,4 +643,37 @@ public class StatisticsServiceImpl implements StatisticsService {
         return personTypeCountList;
 
     }
+
+    /**
+     * 查询各区县的各个规模的企业数量与走访企业次数
+     */
+    @Override
+    public List<ModelCompanyCount> findRegionCompanyModelCompanyCount(Date startDate, Date endDate) {
+        List<ModelCompanyCount> companyCountList = new ArrayList<>();
+        companyCountList.addAll(statisticsCQuery.findRegionCompanyModelCompanyCount(startDate, endDate)); // 企业数量
+        companyCountList.addAll(statisticsCQuery.findRegionCompanyModelSigninCompanyCount(startDate, endDate)); // 走访企业次数
+        return companyCountList;
+    }
+
+    /**
+     * 查询各区县的各个规模的企业用工人数与岗位招聘人数
+     */
+    @Override
+    public List<ModelCompanyCount> findRegionCompanyWorkSituationCount(Date startDate, Date endDate) {
+        List<ModelCompanyCount> companyCountList = new ArrayList<>();
+        companyCountList.addAll(statisticsCQuery.findRegionCompanyWorkSituationCount(startDate, endDate)); // 用工人数
+        companyCountList.addAll(statisticsCQuery.findRegionCompanyRecruitCount(startDate, endDate)); // 岗位招聘人数
+        return companyCountList;
+    }
+
+    /**
+     * 查询各个行业各个规模的企业的岗位招聘人数情况
+     */
+    @Override
+    public List<ModelCompanyCount> findIndustryCompanyWorkSituationCount(Date startDate, Date endDate) {
+        List<ModelCompanyCount> companyCountList = new ArrayList<>();
+        companyCountList.addAll(statisticsCQuery.findIndustryCompanyWorkSituationCount(startDate, endDate));
+        companyCountList.addAll(statisticsCQuery.findIndustryCompanyRecruitCount(startDate, endDate));
+        return companyCountList;
+    }
 }

+ 3 - 0
src/main/java/com/hz/employmentsite/services/service/companyService/CompanyService.java

@@ -4,6 +4,7 @@ import com.github.pagehelper.PageInfo;
 import com.hz.employmentsite.model.PcCompany;
 import com.hz.employmentsite.model.PcFirm;
 import com.hz.employmentsite.model.PcSite;
+import com.hz.employmentsite.vo.companyService.AllCompanyVo;
 import com.hz.employmentsite.vo.companyService.AppCompanyPostVo;
 import com.hz.employmentsite.vo.companyService.CompanyVo;
 import com.hz.employmentsite.vo.dataMap.CompanyPostMapVo;
@@ -23,6 +24,8 @@ public interface CompanyService {
                                 String siteID, Date startDate, Date endDate, String postCountSorter,
                                 String companyTypeID,String industryID, String createUserName);
 
+    List<AllCompanyVo> getAllList();
+
     PageInfo<PcFirm> getFirmNameLikeList(Integer pageIndex, Integer pageSize, String PcFirm);
 
     List<PcCompany> getCompanyBySiteIDList(String siteID);

+ 15 - 0
src/main/java/com/hz/employmentsite/services/service/statistics/StatisticsService.java

@@ -122,4 +122,19 @@ public interface StatisticsService {
      */
     List<PersonTypeJobUserCount> findPersonTypeCountInJobUserData(Integer keyPersonTypeID, Date startDate, Date endDate,
                                                                   String regionCode, String siteID);
+
+    /**
+     * 查询各区县的各个规模的企业数量与走访企业次数
+     */
+    List<ModelCompanyCount> findRegionCompanyModelCompanyCount(Date startDate, Date endDate);
+
+    /**
+     * 查询各区县的各个规模的企业用工人数与岗位招聘人数
+     */
+    List<ModelCompanyCount> findRegionCompanyWorkSituationCount(Date startDate, Date endDate);
+
+    /**
+     * 查询各个行业各个规模的企业的岗位招聘人数情况
+     */
+    List<ModelCompanyCount> findIndustryCompanyWorkSituationCount(Date startDate, Date endDate);
 }

+ 109 - 0
src/main/java/com/hz/employmentsite/util/RedisClient.java

@@ -0,0 +1,109 @@
+package com.hz.employmentsite.util;
+
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class RedisClient {
+
+    @Resource
+    private RedisTemplate<String, Object> redisTemplate;
+
+    /*
+     * @ClassName RedisClient
+     * @Desc TODO   设置缓存(没有时间限制)
+     * @Date 2021-07-24 16:11
+     * @Version 1.0
+     */
+    public void set(String key, Object value) {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /*
+     * @ClassName RedisClient
+     * @Desc TODO   设置缓存(有时间限制,单位为 秒)
+     * @Date 2021-07-24 16:11
+     * @Version 1.0
+     */
+    public void set(String key, Object value, long timeout) {
+        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
+    }
+
+    /*
+     * @ClassName RedisClient
+     * @Desc TODO   删除缓存,并返回是否删除成功
+     * @Date 2021-07-24 16:11
+     * @Version 1.0
+     */
+    public boolean delete(String key) {
+        redisTemplate.delete(key);
+        // 如果还存在这个 key 就证明删除失败
+        // 不存在就证明删除成功
+        return !redisTemplate.hasKey(key);
+    }
+
+    /*
+     * @ClassName RedisClient
+     * @Desc TODO   取出缓存
+     * @Date 2021-07-24 16:12
+     * @Version 1.0
+     */
+    public Object get(String key) {
+        if (redisTemplate.hasKey(key)) {
+            return redisTemplate.opsForValue().get(key);
+        } else {
+            return null;
+        }
+    }
+
+    /*
+     * @ClassName RedisClient
+     * @Desc TODO   获取失效时间(-2:失效 / -1:没有时间限制)
+     * @Date 2021-07-24 16:15
+     * @Version 1.0
+     */
+    public long getExpire(String key) {
+        // 判断是否存在
+        if (redisTemplate.hasKey(key)) {
+            return redisTemplate.getExpire(key);
+        } else {
+            return Long.parseLong(-2 + "");
+        }
+    }
+
+    /**
+     * 设置setl键值
+     *
+     * @param key   建
+     * @param value 值
+     */
+    public void setSetValue(String key, Object value) {
+        redisTemplate.opsForSet().add(key, value);
+    }
+
+    /**
+     * 删除键值
+     *
+     * @param key   建
+     * @param value 值
+     */
+    public void removeSetValue(String key, Object value) {
+        redisTemplate.opsForSet().remove(key, value);
+    }
+
+
+
+    /**
+     * 判断一个值是否存在于set集合
+     *
+     * @param key   建
+     * @param value 值
+     * @return
+     */
+    public boolean judgeValueIsInSet(String key, Object value) {
+        return redisTemplate.opsForSet().isMember(key, value);
+    }
+}

+ 126 - 0
src/main/java/com/hz/employmentsite/vo/companyService/AllCompanyVo.java

@@ -0,0 +1,126 @@
+package com.hz.employmentsite.vo.companyService;
+
+import com.hz.employmentsite.model.PcCreditRecord;
+import com.hz.employmentsite.util.datarange.annotations.InstitutionID;
+import com.hz.employmentsite.vo.baseSettings.LabelVo;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 为岗位推荐设计查询时无数据权限,可查询全部的企业
+ */
+@Data
+public class AllCompanyVo {
+
+    public String companyID;
+
+    public String siteID;
+
+    public String regionCode;
+
+    public String streetCode;
+
+    public String companyName;
+
+    public String companyCode;
+
+    public Integer companyModel;
+    public String  companyModelType;
+
+    public String companyModelStr;
+
+    public String workSituation;
+
+    public Integer companyType;
+    public String  companyTypeName;
+
+    public String  companyTypeStr;
+
+    public String companyAddress;
+
+    public String userName;
+
+    public String userMobile;
+
+    public String companyEmail;
+
+    public String frName;
+
+    public Date validDate;
+    public String validDateStr;
+
+    public Integer recordStatus;
+    public String recordStatusName;
+
+    public String createUserID;
+    public String createUserName;
+
+    public Date createTime;
+
+    public String modifyUserID;
+
+    public String modifyUserName;
+
+    public Date modifyTime;
+
+    public String SiteName;
+
+    public String regionName;
+
+    public String streetName;
+
+    public String businScope;
+
+    public String companyDesc;
+
+    public int postCount;
+
+    public String longitude;
+    public String latitude;
+
+    public Date establishmentTime;
+    public BigDecimal registeredCapital;
+    public Integer registeredCapitalType;
+    public String RegisteredCapitalTypeName;
+    public String registeredCapitalTypeStr;
+    public String signInPoliticalArea;
+    public String signInPoliticalAreaName;
+
+    public String industryID;
+    public String industryName;
+    public String showIndustryName;
+    public Integer estateCategoryID;
+    public String estateCategoryName;
+    public Integer tagID;
+    public String tagName;
+
+    public String website;
+    public String bonus;
+    public String openId;
+
+    public String errorMessage;
+
+    public Integer insuredCount;
+
+    public Integer isShortage;
+    public String isShortageName;
+    @InstitutionID
+    public String institutionID;
+
+    public String loginUserID;
+
+    public List<LabelVo> listLabel;
+
+    public List<PcCreditRecord> creditRecordList;
+
+    // JSON列表数据
+    public String labelList;
+    public String postList;
+
+    // 经纬度直线距离
+    public BigDecimal distance;
+
+}

+ 10 - 0
src/main/java/com/hz/employmentsite/vo/statistics/company/ModelCompanyCount.java

@@ -8,9 +8,19 @@ public class ModelCompanyCount {
 
     private String regionName;
 
+    private String parentIndustryName;
+
+    private String industryName;
+
     private Integer companyModel;
 
     private String companyModelName;
 
     private int companyCount;
+
+    private int signinCompanyCount;
+
+    private int workSituationCount;
+
+    private int recruitCount;
 }

+ 6 - 0
src/main/resources/mapping/cquery/CompanyCQuery.xml

@@ -101,6 +101,12 @@
             company.CreateTime desc
         </if>
     </select>
+
+    <select id="getAllList" resultType="com.hz.employmentsite.vo.companyService.AllCompanyVo">
+        select company.*
+        from pc_company company
+    </select>
+
     <select id="getFirmNameLikeList" resultType="com.hz.employmentsite.model.PcFirm">
         select id,FirmName
         from pc_firm

+ 196 - 0
src/main/resources/mapping/cquery/StatisticsCQuery.xml

@@ -1026,4 +1026,200 @@
         ORDER BY
             jobuser.KeyPersonTypeID DESC
     </select>
+
+    <select id="findRegionCompanyModelCompanyCount" resultType="com.hz.employmentsite.vo.statistics.company.ModelCompanyCount">
+        SELECT
+            area.`code` AS regionCode,
+            area.`name` AS regionName,
+            company.CompanyModel,
+            dict.`Name` AS companyModelName,
+            COUNT( company.CompanyID ) AS companyCount
+        FROM
+            area_code area
+                LEFT JOIN pc_site site ON area.`code` = site.RegionCode
+                LEFT JOIN pc_company company ON site.SiteID = company.SiteID
+                LEFT JOIN sys_dictionary_item dict ON company.CompanyModel = dict.`Value`
+                AND dict.DictionaryCode = 'CompanyModel'
+        WHERE
+            area.lv = 3
+            AND area.`code` != '441301000000000'
+	        AND company.CompanyModel IS NOT NULL
+            <if test="startDate != null">
+                and DATE(company.CreateTime) <![CDATA[ >= ]]> DATE(#{startDate})
+            </if>
+            <if test="endDate != null ">
+                and DATE(company.CreateTime) <![CDATA[ <= ]]> DATE(#{endDate})
+            </if>
+        GROUP BY
+            area.`code`,
+            area.`name`,
+            company.CompanyModel,
+            dict.`Name`
+        ORDER BY
+            area.`code`
+    </select>
+
+    <select id="findRegionCompanyModelSigninCompanyCount" resultType="com.hz.employmentsite.vo.statistics.company.ModelCompanyCount">
+        SELECT
+            area.`code` AS regionCode,
+            area.`name` AS regionName,
+            company.CompanyModel,
+            dict.`Name` AS companyModelName,
+            COUNT( signin.CompanyID ) AS signinCompanyCount
+        FROM
+            area_code area
+                LEFT JOIN pc_site site ON area.`code` = site.RegionCode
+                LEFT JOIN pc_company company ON site.SiteID = company.SiteID
+                LEFT JOIN pc_signin signin ON company.CompanyID = signin.CompanyID
+                LEFT JOIN sys_dictionary_item dict ON company.CompanyModel = dict.`Value`
+                AND dict.DictionaryCode = 'CompanyModel'
+        WHERE
+            area.lv = 3
+            AND area.`code` != '441301000000000'
+            AND company.CompanyModel IS NOT NULL
+            AND signin.SigninType = 1
+            <if test="startDate != null">
+                and DATE(signin.CreateTime) <![CDATA[ >= ]]> DATE(#{startDate})
+            </if>
+            <if test="endDate != null ">
+                and DATE(signin.CreateTime) <![CDATA[ <= ]]> DATE(#{endDate})
+            </if>
+        GROUP BY
+            area.`code`,
+            area.`name`,
+            company.CompanyModel,
+            dict.`Name`
+        ORDER BY
+            area.`code`
+    </select>
+
+    <select id="findRegionCompanyWorkSituationCount" resultType="com.hz.employmentsite.vo.statistics.company.ModelCompanyCount">
+        SELECT
+            area.`code` AS regionCode,
+            area.`name` AS regionName,
+            company.CompanyModel,
+            dict.`Name` AS companyModelName,
+            SUM( company.workSituation ) AS workSituationCount
+        FROM
+            area_code area
+                LEFT JOIN pc_site site ON area.`code` = site.RegionCode
+                LEFT JOIN pc_company company ON site.SiteID = company.SiteID
+                LEFT JOIN sys_dictionary_item dict ON company.CompanyModel = dict.`Value`
+                AND dict.DictionaryCode = 'CompanyModel'
+        WHERE
+            area.lv = 3
+            AND area.`code` != '441301000000000'
+            AND company.CompanyModel IS NOT NULL
+            AND company.WorkSituation IS NOT NULL
+            <if test="startDate != null">
+                and DATE(company.CreateTime) <![CDATA[ >= ]]> DATE(#{startDate})
+            </if>
+            <if test="endDate != null ">
+                and DATE(company.CreateTime) <![CDATA[ <= ]]> DATE(#{endDate})
+            </if>
+        GROUP BY
+            area.`code`,
+            area.`name`,
+            company.CompanyModel,
+            dict.`Name`
+        ORDER BY
+            area.`code`
+    </select>
+
+    <select id="findRegionCompanyRecruitCount" resultType="com.hz.employmentsite.vo.statistics.company.ModelCompanyCount">
+        SELECT
+            area.`code` AS regionCode,
+            area.`name` AS regionName,
+            company.CompanyModel,
+            dict.`Name` AS companyModelName,
+            SUM( post.recruitCount ) AS recruitCount
+        FROM
+            area_code area
+                LEFT JOIN pc_site site ON area.`code` = site.RegionCode
+                LEFT JOIN pc_company company ON site.SiteID = company.SiteID
+                LEFT JOIN pc_post post ON company.CompanyID = post.CompanyID
+                LEFT JOIN sys_dictionary_item dict ON company.CompanyModel = dict.`Value`
+                AND dict.DictionaryCode = 'CompanyModel'
+        WHERE
+            area.lv = 3
+            AND area.`code` != '441301000000000'
+            AND company.CompanyModel IS NOT NULL
+            AND post.RecruitCount IS NOT NULL
+            <if test="startDate != null">
+                and DATE(post.CreateTime) <![CDATA[ >= ]]> DATE(#{startDate})
+            </if>
+            <if test="endDate != null ">
+                and DATE(post.CreateTime) <![CDATA[ <= ]]> DATE(#{endDate})
+            </if>
+        GROUP BY
+            area.`code`,
+            area.`name`,
+            company.CompanyModel,
+            dict.`Name`
+        ORDER BY
+            area.`code`
+    </select>
+
+    <select id="findIndustryCompanyWorkSituationCount" resultType="com.hz.employmentsite.vo.statistics.company.ModelCompanyCount">
+        SELECT
+            pIndustry.industryName AS parentIndustryName,
+            industry.industryName,
+            company.CompanyModel,
+            dict.`Name` AS companyModelName,
+            SUM( company.WorkSituation ) AS workSituationCount
+        FROM
+            pc_industry industry
+                LEFT JOIN pc_industry pIndustry ON industry.parentId = pIndustry.industryId
+                LEFT JOIN pc_company company ON company.IndustryID = industry.industryId
+                LEFT JOIN sys_dictionary_item dict ON company.CompanyModel = dict.`Value`
+                AND dict.DictionaryCode = 'CompanyModel'
+        WHERE
+            industry.parentId != ''
+	        AND industry.parentId IS NOT NULL
+            <if test="startDate != null">
+                and DATE(company.CreateTime) <![CDATA[ >= ]]> DATE(#{startDate})
+            </if>
+            <if test="endDate != null ">
+                and DATE(company.CreateTime) <![CDATA[ <= ]]> DATE(#{endDate})
+            </if>
+        GROUP BY
+            pIndustry.industryName,
+            industry.industryName,
+            company.CompanyModel,
+            dict.`Name`
+        ORDER BY
+            industry.parentId
+    </select>
+
+    <select id="findIndustryCompanyRecruitCount" resultType="com.hz.employmentsite.vo.statistics.company.ModelCompanyCount">
+        SELECT
+            pIndustry.industryName AS parentIndustryName,
+            industry.industryName,
+            company.CompanyModel,
+            dict.`Name` AS companyModelName,
+            COUNT( post.RecruitCount ) AS recruitCount
+        FROM
+            pc_industry industry
+                LEFT JOIN pc_industry pIndustry ON industry.parentId = pIndustry.industryId
+                LEFT JOIN pc_company company ON company.IndustryID = industry.industryId
+                LEFT JOIN pc_post post on company.CompanyID = post.CompanyID
+                LEFT JOIN sys_dictionary_item dict ON company.CompanyModel = dict.`Value`
+                AND dict.DictionaryCode = 'CompanyModel'
+        WHERE
+            industry.parentId != ''
+	        AND industry.parentId IS NOT NULL
+            <if test="startDate != null">
+                and DATE(post.CreateTime) <![CDATA[ >= ]]> DATE(#{startDate})
+            </if>
+            <if test="endDate != null ">
+                and DATE(post.CreateTime) <![CDATA[ <= ]]> DATE(#{endDate})
+            </if>
+        GROUP BY
+            pIndustry.industryName,
+            industry.industryName,
+            company.CompanyModel,
+            dict.`Name`
+        ORDER BY
+            industry.parentId
+    </select>
 </mapper>

+ 13 - 0
vue/src/api/companyService/company.ts

@@ -14,6 +14,19 @@ export function getList(params: any) {
   );
 }
 
+export function getAllList() {
+  return request<object>(
+    {
+      url: "companyService/company/getAllList",
+      method: 'get',
+      params: {},
+    },
+    {
+      isNew: true,
+    },
+  );
+}
+
 export function getCompanyById(id: string, loginUserID: any,isAllCompany: boolean) {
   return request({
     url: 'companyService/company/getCompanyByID',

+ 1 - 0
vue/src/api/login/index.ts

@@ -17,6 +17,7 @@ export function login(data: API.LoginParams) {
     },
     {
       isNew: true,
+      isGetDataDirectly: false
     },
   );
 }

+ 48 - 0
vue/src/api/statistics/index.ts

@@ -324,3 +324,51 @@ export function getPersonTypeCountInJobUserData(params: any) {
     },
   );
 }
+
+/**
+ * 查询各区县的各个规模的企业数量与走访企业次数
+ */
+export function getRegionCompanyModelCompanyCount(params: any) {
+  return request<object>(
+    {
+      url: 'statistics/companyModelCompanyCountInRegion',
+      method: 'get',
+      params: params,
+    },
+    {
+      isNew: true,
+    },
+  );
+}
+
+/**
+ * 查询各区县的各个规模的企业用工人数与岗位招聘人数
+ */
+export function getRegionCompanyWorkSituationCount(params: any) {
+  return request<object>(
+    {
+      url: 'statistics/workSituationCountInRegion',
+      method: 'get',
+      params: params,
+    },
+    {
+      isNew: true,
+    },
+  );
+}
+
+/**
+ * 查询各个行业各个规模的企业的岗位招聘人数情况
+ */
+export function getIndustryCompanyWorkSituationCount(params: any) {
+  return request<object>(
+    {
+      url: 'statistics/workSituationCountInIndustry',
+      method: 'get',
+      params: params,
+    },
+    {
+      isNew: true,
+    },
+  );
+}

+ 1 - 0
vue/src/router/asyncModules/statistics.ts

@@ -4,4 +4,5 @@ export default {
   'views/statistics/JobUserCount': () => import('@/views/statistics/JobUserCount.vue'),
   'views/statistics/YearSystemApplyCount': () => import('@/views/statistics/YearSystemApplyCount.vue'),
   'views/statistics/SiteStatistics': () => import('@/views/statistics/SiteStatistics.vue'),
+  'views/statistics/CompanyStatistics': () => import('@/views/statistics/CompanyStatistics.vue'),
 };

+ 13 - 5
vue/src/store/modules/user.ts

@@ -99,11 +99,19 @@ export const useUserStore = defineStore({
     async login(params: API.LoginParams) {
       try {
 
-        const data = await login(params);
-        this.setToken(data.token);
-        this.setDataRangeList(data.dataRangeList);
-        this.setPermissionList(data.permissionList);
-        return this.afterLogin();
+        const result: any = await login(params);
+        if (result.code == 200) {
+          this.setToken(result.data.token);
+          this.setDataRangeList(result.data.dataRangeList);
+          this.setPermissionList(result.data.permissionList);
+          return this.afterLogin();
+        } else if (result.code == 20001 || result.code == 20002) {
+          // 登录失败返回错误
+          return {
+            code: result.code,
+            message: result.message,
+          }
+        }
 
       } catch (error) {
         return Promise.reject(error);

+ 5 - 0
vue/src/utils/request.ts

@@ -75,6 +75,11 @@ service.interceptors.response.use(
     // if the custom code is not 200, it is judged as an error.
 
     if (res.code && res.code !== "200") {
+      // 处理账号密码输入错误警告的返回
+      if (res.cpde == "20001" || res.code == "20002") {
+        return res;
+      }
+
       //$message.error(res.message || UNKNOWN_ERROR);
 
       // Illegal token

+ 4 - 3
vue/src/views/jobUserManager/jobhunt/edit.vue

@@ -12,7 +12,8 @@
               @search="selectJobUserList"
               @change="jobUserChange"
               :field-names="{
-                            value:'name',
+                            label:'name',
+                            value:'jobUserID',
                           }"
             >
               <template #option="item">
@@ -257,7 +258,6 @@ export default defineComponent({
       setProfessionId(value);
     }
     function jobUserChange(value: any) {
-      formData.dataModel.name = value;
       setJobUserId(value);
     }
 
@@ -272,8 +272,9 @@ export default defineComponent({
     }
 
     function setJobUserId(value:any){
-      const curJobUser = jobUserList.value.find(x => x.name === value);
+      const curJobUser = jobUserList.value.find(x => x.jobUserID === value);
       if (curJobUser) {
+        formData.dataModel.jobUserName = curJobUser.name;
         formData.dataModel.jobUserID = curJobUser.jobUserID;
       } else {
         formData.dataModel.jobUserID = null;

+ 8 - 5
vue/src/views/jobUserManager/jobhunt/recommend.vue

@@ -206,13 +206,13 @@ import {getRecommendCompanyPostList, addRecommend,getProfessionLikeList, getComp
 import {getPaginationTotalTitle} from '@/utils/common';
 import dayjs from 'dayjs';
 import {message, SelectProps} from "ant-design-vue";
-import {get} from "@/api/common";
 import {debounce} from "lodash-es";
 import {getAllSite} from "@/api/baseSettings/siteInfo";
 import {getRegionCodeList} from '@/api/system/area/index';
 import {getSysDictionaryList} from "@/api/system/dictionary";
 import CompanyDetailModel from "./companyDetail.vue";
 import PostDetailModel from "./postDetail.vue";
+import {getAllList} from "@/api/companyService/company";
 
 export default defineComponent({
   name: 'RecommendCompanyPostList',
@@ -235,10 +235,6 @@ export default defineComponent({
     const recommendPostWhereList = ref([{label:'岗位',value:1},{label:'相关行业',value:2}] as any);
     const jobUserID = ref();
 
-    get('companyService/company/getList', {pageIndex: 1, pageSize: 9999}).then(result => {
-      companyList.value = result.list;
-    });
-
     function companyChange(value: any) {
       getCompanyProfessionLikeList({
         pageIndex: 1,
@@ -251,6 +247,12 @@ export default defineComponent({
       })
     }
 
+    function getCompanyList() {
+      getAllList().then((result: any) => {
+        companyList.value = result;
+      })
+    }
+
     const getCultureLevelList = async function () {
       const data: any = await getSysDictionaryList("CultureLevel");
       cultureLevelList.value = data;
@@ -431,6 +433,7 @@ export default defineComponent({
 
     const loadData = async function () {
       formState.loading = true;
+      await getCompanyList();
       await getCultureLevelList();
       await getWorkYearTypeList();
       await getAllSites();

+ 32 - 8
vue/src/views/login/index.vue

@@ -23,6 +23,11 @@
           <template #prefix><lock-outlined type="user" /></template>
         </a-input>
       </a-form-item>
+        <a-form-item v-if="loginErrorInfo.isShow">
+          <div style="color: red">
+            {{ loginErrorInfo.message }}
+          </div>
+        </a-form-item>
 <!--      <a-form-item>
         <a-input
           v-model:value="state.formInline.verifyCode"
@@ -69,6 +74,10 @@
       captchaId: '',
     },
   });
+  const loginErrorInfo = reactive({
+    isShow: false,
+    message: ""
+  })
 
   const route = useRoute();
   const router = useRouter();
@@ -96,19 +105,34 @@
     console.log(state.formInline);
     // params.password = md5(password)
 
-    const [err] = await to(userStore.login(state.formInline));
-    if (err) {
+    await to(userStore.login(state.formInline)).then((result: any) => {
+      const find = result.find((value: any) => value != null);
+      if (find.code || find.message) {
+        if (find.code == "20001" || find.code == "20002") {
+          // 提示用户剩余允许错误次数
+          loginErrorInfo.isShow = true;
+          loginErrorInfo.message = find.message;
+        }
+        Modal.error({
+          title: () => '提示',
+          content: () => find.message,
+        });
+        setCaptcha();
+      } else {
+        message.success('登录成功!');
+        loginErrorInfo.isShow = false;
+        setTimeout(() => router.replace((route.query.redirect as string) ?? '/'));
+      }
+    }).catch((err: any) => {
       Modal.error({
         title: () => '提示',
         content: () => err.message,
       });
       setCaptcha();
-    } else {
-      message.success('登录成功!');
-      setTimeout(() => router.replace((route.query.redirect as string) ?? '/'));
-    }
-    state.loading = false;
-    message.destroy();
+    }).finally(() => {
+      state.loading = false;
+      message.destroy();
+    })
   };
 </script>
 

+ 489 - 0
vue/src/views/statistics/CompanyStatistics.vue

@@ -0,0 +1,489 @@
+<template>
+  <div class="card-search">
+    <a-form
+      ref="formRef"
+      name="advanced_search"
+      class="ant-advanced-search-form"
+      :model="searchParams"
+    >
+      <a-row :gutter="24">
+        <a-col :span="6">
+          <a-form-item label="日期" :label-col="{ span: 8 }" name="emphasisTypeId">
+            <a-range-picker format="YYYY-MM-DD" :placeholder="['开始日期', '结束日期']" v-model:value="reportDate"
+                            @change="onRangeChange"/>
+          </a-form-item>
+        </a-col>
+        <a-col :span="6" style="text-align: left">
+          <a-button type="primary" html-type="submit" @click="onFinish">查询</a-button>
+          <a-button
+            style="margin: 0 8px"
+            @click="
+              () => {
+                formRef.resetFields();
+                onFinish();
+              }
+            ">重置
+          </a-button>
+        </a-col>
+      </a-row>
+    </a-form>
+    <!-- 操作按钮 -->
+    <a-row class="edit-operation" style="margin-bottom: 20px">
+      <a-col :span="24" class="flex-space-between">
+        <div>
+          <a-radio-group v-model:value="searchType" button-style="solid" @change="searchTypeChange">
+            <a-radio-button value="companyCount">各区县企业入库与走访情况统计</a-radio-button>
+            <a-radio-button value="workSituationCount">各区县企业用工人数与岗位招聘人数统计</a-radio-button>
+            <a-radio-button value="industryWorkSituationCount">各行业企业用工人数与岗位招聘人数统计</a-radio-button>
+          </a-radio-group>
+        </div>
+        <div>
+        </div>
+      </a-col>
+    </a-row>
+    <!-- 数据展示 -->
+    <!-- 企业入库与走访情况统计 -->
+    <div v-show="searchType == 'companyCount'">
+      <a-table :columns="companyCountDataTableColumns" :data-source="companyCountDataList"
+               :scroll="{ x:'100%' }"
+               :loading="searchLoading"
+               :pagination="false"
+               bordered>
+      </a-table>
+    </div>
+    <!-- 企业用工人数与岗位招聘人数统计 -->
+    <div v-show="searchType == 'workSituationCount'">
+      <a-table :columns="workSituationCountDataTableColumns" :data-source="workSituationCountDataList"
+               :scroll="{ x:'100%' }"
+               :loading="searchLoading"
+               :pagination="false"
+               bordered>
+      </a-table>
+    </div>
+    <!-- 企业用工人数与岗位招聘人数统计 -->
+    <div v-show="searchType == 'industryWorkSituationCount'">
+      <a-table :columns="industryWorkSituationCountDataTableColumns" :data-source="industryWorkSituationCountDataList"
+               :scroll="{ x:'100%' }"
+               :loading="searchLoading"
+               :pagination="false"
+               bordered>
+      </a-table>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {onMounted, reactive, ref} from "vue";
+import type {RangeValue} from "ant-design-vue/es/vc-picker/interface";
+import dayjs from "dayjs";
+import {getSysDictionaryList} from "@/api/system/dictionary";
+import {
+  getIndustryCompanyWorkSituationCount,
+  getRegionCompanyModelCompanyCount,
+  getRegionCompanyWorkSituationCount
+} from "@/api/statistics";
+
+const searchParams = reactive({
+  startDate: "",
+  endDate: "",
+});
+const reportDate = ref<RangeValue<any>>();
+const searchType = ref("companyCount");
+const formRef = ref();
+const searchLoading = ref(false);
+const companyModelList = ref<Array<any>>();
+// 企业入库与走访情况统计表结构
+const companyCountDataTableColumns = ref<Array<any>>([
+  {
+    title: '区县', dataIndex: 'regionName', key: 'regionName', align: "center", width: 280
+  },
+]);
+const companyCountDataList = ref<Array<any>>([]);
+const companyCountKeyTemp = ref<Array<any>>([]);
+// 企业用工人数与岗位招聘人数统计表结构
+const workSituationCountDataTableColumns = ref<Array<any>>([
+  {
+    title: '区县', dataIndex: 'regionName', key: 'regionName', align: "center", width: 280
+  },
+]);
+const workSituationCountDataList = ref<Array<any>>([]);
+const workSituationCountKeyTemp = ref<Array<any>>([]);
+// 各行业企业用工人数与岗位招聘人数统计表结构
+const industryWorkSituationCountDataTableColumns = ref<Array<any>>([
+  {
+    title: '产业分类', dataIndex: 'estateCategoryName', key: 'estateCategoryName', align: "center", width: 150,
+    customCell: (record, index: any) => {
+      const obj = {
+        colSpan: 1,
+        rowSpan: 1,
+      };
+      if (record.estateCategoryName == '合计' || record.estateCategoryName == '小计') {
+        obj.colSpan = 3;
+      }
+      if (index === 0 || record.estateCategoryName !== industryWorkSituationCountDataList.value[index - 1].estateCategoryName) {
+        for (let i = index + 1; i < industryWorkSituationCountDataList.value.length; i++) {
+          if (industryWorkSituationCountDataList.value[i].estateCategoryName == record.estateCategoryName) {
+            obj.rowSpan++;
+          } else {
+            break;
+          }
+        }
+      } else {
+        obj.rowSpan = 0;
+      }
+      return obj;
+    },
+  }, {
+    title: '所属行业', dataIndex: 'parentIndustryName', key: 'parentIndustryName', align: "center", width: 150,
+    customCell: (record, index: any) => {
+      const obj = {
+        colSpan: 1,
+        rowSpan: 1,
+      };
+      if (record.estateCategoryName == '合计' || record.estateCategoryName == '小计') {
+        obj.colSpan = 0;
+      }
+      if (index === 0 || record.parentIndustryName !== industryWorkSituationCountDataList.value[index - 1].parentIndustryName) {
+        for (let i = index + 1; i < industryWorkSituationCountDataList.value.length; i++) {
+          if (industryWorkSituationCountDataList.value[i].parentIndustryName == record.parentIndustryName) {
+            obj.rowSpan++;
+          } else {
+            break;
+          }
+        }
+      } else {
+        obj.rowSpan = 0;
+      }
+      return obj;
+    },
+  }, {
+    title: '行业名称', dataIndex: 'industryName', key: 'industryName', align: "center", width: 200,
+    customCell: (record) => {
+      const obj = {
+        colSpan: 1,
+        rowSpan: 1,
+      };
+      if (record.estateCategoryName == '合计' || record.estateCategoryName == '小计') {
+        obj.colSpan = 0;
+      }
+      return obj;
+    },
+  },
+]);
+const industryWorkSituationCountDataList = ref<Array<any>>([]);
+const industryWorkSituationCountKeyTemp = ref<Array<any>>([]);
+
+// 时间段变更事件
+const onRangeChange = (dateString: [string, string]) => {
+  searchParams.startDate = dateString != null ? dayjs(dateString[0]).format("YYYY-MM-DD") : "";
+  searchParams.endDate = dateString != null ? dayjs(dateString[1]).format("YYYY-MM-DD") : "";
+  onFinish();
+};
+
+function onFinish() {
+  searchTypeChange();
+}
+
+// 获取企业规模
+function getCompanyModel() {
+  getSysDictionaryList("CompanyModel").then((result: any) => {
+    companyModelList.value = result;
+    // 生成表结构
+    result.forEach((item: any) => {
+      const key = 'companyModel' + item.value;
+      // 企业入库与走访情况统计表结构
+      companyCountKeyTemp.value.push(...[key + 'Count', key + 'SigninCount']);
+      companyCountDataTableColumns.value.push({
+        title: item.name, dataIndex: key, key, align: "center",
+        children: [
+          {
+            title: '入库',
+            dataIndex: key + 'Count',
+            key: key + 'Count',
+            align: "center"
+          },
+          {
+            title: '走访',
+            dataIndex: key + 'SigninCount',
+            key: key + 'SigninCount',
+            align: "center"
+          },
+        ]
+      })
+      // 区县企业用工人数与岗位招聘人数统计表结构
+      workSituationCountKeyTemp.value.push(...[key + 'WorkSituationCount', key + 'RecruitCount']);
+      workSituationCountDataTableColumns.value.push({
+        title: item.name, dataIndex: key, key, align: "center",
+        children: [
+          {
+            title: '用工人数',
+            dataIndex: key + 'WorkSituationCount',
+            key: key + 'WorkSituationCount',
+            align: "center"
+          },
+          {
+            title: '岗位人数',
+            dataIndex: key + 'RecruitCount',
+            key: key + 'RecruitCount',
+            align: "center"
+          },
+        ]
+      })
+      // 行业企业用工人数与岗位招聘人数统计表结构
+      industryWorkSituationCountKeyTemp.value.push(...[key + 'WorkSituationCount', key + 'RecruitCount']);
+      industryWorkSituationCountDataTableColumns.value.push({
+        title: item.name, dataIndex: key, key, align: "center",
+        children: [
+          {
+            title: '用工人数',
+            dataIndex: key + 'WorkSituationCount',
+            key: key + 'WorkSituationCount',
+            align: "center"
+          },
+          {
+            title: '岗位人数',
+            dataIndex: key + 'RecruitCount',
+            key: key + 'RecruitCount',
+            align: "center"
+          },
+        ]
+      })
+    })
+  });
+}
+
+function searchTypeChange() {
+  if (searchType.value == "companyCount") {
+    searchLoading.value = true;
+    companyCountDataList.value = [];
+    getRegionCompanyModelCompanyCount({...searchParams}).then((result: any) => {
+      // 初始化合计数据
+      let count = {
+        regionCode: -1,
+        regionName: "合计",
+      }
+      // 初始化字段值为O
+      companyCountKeyTemp.value.forEach((key: any) => {
+        count[key] = 0;
+      })
+      result.forEach((resItem: any) => {
+        const key = 'companyModel' + resItem.companyModel;
+        // 查询获取区县数据的下标,保证每个区县只存在一条数据
+        const findIndex = companyCountDataList.value.findIndex((find: any) => find.regionCode == resItem.regionCode);
+        if (findIndex > -1) {
+          // 区县已存在,修改这条数据
+          if (resItem.companyCount > 0) {
+            companyCountDataList.value[findIndex][key + 'Count'] = resItem.companyCount;
+            count[key + 'Count'] += resItem.companyCount;
+          }
+          if (resItem.signinCompanyCount > 0) {
+            companyCountDataList.value[findIndex][key + 'SigninCount'] = resItem.signinCompanyCount;
+            count[key + 'SigninCount'] += resItem.signinCompanyCount;
+          }
+        } else {
+          // 不存在,新增一条数据
+          const newData = {
+            regionCode: resItem.regionCode,
+            regionName: resItem.regionName,
+          }
+          companyCountKeyTemp.value.forEach((key: any) => {
+            newData[key] = 0;
+          })
+          if (resItem.companyCount > 0) {
+            newData[key + 'Count'] = resItem.companyCount;
+            count[key + 'Count'] += resItem.companyCount;
+          }
+          if (resItem.signinCompanyCount > 0) {
+            newData[key + 'SigninCount'] = resItem.signinCompanyCount;
+            count[key + 'SigninCount'] += resItem.signinCompanyCount;
+          }
+          companyCountDataList.value.push(newData);
+        }
+      });
+      console.log(count);
+      companyCountDataList.value.push(count);
+    }).finally(() => {
+      searchLoading.value = false;
+    })
+  }
+  if (searchType.value == "workSituationCount") {
+    searchLoading.value = true;
+    workSituationCountDataList.value = [];
+    getRegionCompanyWorkSituationCount({...searchParams}).then((result: any) => {
+      // 初始化合计数据
+      let count = {
+        regionCode: -1,
+        regionName: "合计",
+      }
+      // 初始化字段值为O
+      workSituationCountKeyTemp.value.forEach((key: any) => {
+        count[key] = 0;
+      });
+      result.forEach((resItem: any) => {
+        const key = 'companyModel' + resItem.companyModel;
+        // 查询获取区县数据的下标,保证每个区县只存在一条数据
+        const findIndex = workSituationCountDataList.value.findIndex((find: any) => find.regionCode == resItem.regionCode);
+        if (findIndex > -1) {
+          // 区县已存在,修改这条数据
+          if (resItem.workSituationCount > 0) {
+            workSituationCountDataList.value[findIndex][key + 'WorkSituationCount'] = resItem.workSituationCount;
+            count[key + 'WorkSituationCount'] += resItem.workSituationCount;
+          }
+          if (resItem.recruitCount > 0) {
+            workSituationCountDataList.value[findIndex][key + 'RecruitCount'] = resItem.recruitCount;
+            count[key + 'RecruitCount'] += resItem.recruitCount;
+          }
+        } else {
+          // 不存在,新增一条数据
+          const newData = {
+            regionCode: resItem.regionCode,
+            regionName: resItem.regionName,
+          }
+          workSituationCountKeyTemp.value.forEach((key: any) => {
+            newData[key] = 0;
+          })
+          if (resItem.workSituationCount > 0) {
+            newData[key + 'WorkSituationCount'] = resItem.workSituationCount;
+            count[key + 'WorkSituationCount'] += resItem.workSituationCount;
+          }
+          if (resItem.recruitCount > 0) {
+            newData[key + 'RecruitCount'] = resItem.recruitCount;
+            count[key + 'RecruitCount'] += resItem.recruitCount;
+          }
+          workSituationCountDataList.value.push(newData);
+        }
+      });
+      workSituationCountDataList.value.push(count);
+    }).finally(() => {
+      searchLoading.value = false;
+    })
+  }
+  if (searchType.value == "industryWorkSituationCount") {
+    searchLoading.value = true;
+    industryWorkSituationCountDataList.value = [];
+    getIndustryCompanyWorkSituationCount({...searchParams}).then((result: any) => {
+      // 初始化合计数据
+      let count = {
+        estateCategoryId: -1,
+        estateCategoryName: "合计",
+        parentIndustryName: "合计",
+        industryName: "合计"
+      }
+      // 初始化字段值为O
+      industryWorkSituationCountKeyTemp.value.forEach((key: any) => {
+        count[key] = 0;
+      });
+      result.forEach((resItem: any) => {
+        const key = 'companyModel' + resItem.companyModel;
+        // 查询获取行业数据的下标,保证每个区县只存在一条数据
+        const findIndex = industryWorkSituationCountDataList.value.findIndex((find: any) => find.industryName == resItem.industryName);
+        if (findIndex > -1) {
+          // 行业已存在,修改这条数据
+          if (resItem.workSituationCount > 0) {
+            industryWorkSituationCountDataList.value[findIndex][key + 'WorkSituationCount'] = resItem.workSituationCount;
+            count[key + 'WorkSituationCount'] += resItem.workSituationCount;
+          }
+          if (resItem.recruitCount > 0) {
+            industryWorkSituationCountDataList.value[findIndex][key + 'RecruitCount'] = resItem.recruitCount;
+            count[key + 'RecruitCount'] += resItem.recruitCount;
+          }
+        } else {
+          // 不存在,新增一条数据
+          const newData = {
+            parentIndustryName: resItem.parentIndustryName,
+            industryName: resItem.industryName,
+          }
+          setEstateCategoryName(newData);
+          industryWorkSituationCountKeyTemp.value.forEach((key: any) => {
+            newData[key] = 0;
+          })
+          if (resItem.workSituationCount > 0) {
+            newData[key + 'WorkSituationCount'] = resItem.workSituationCount;
+            count[key + 'WorkSituationCount'] += resItem.workSituationCount;
+          }
+          if (resItem.recruitCount > 0) {
+            newData[key + 'RecruitCount'] = resItem.recruitCount;
+            count[key + 'RecruitCount'] += resItem.recruitCount;
+          }
+          industryWorkSituationCountDataList.value.push(newData);
+        }
+      });
+      // 按产业分类进行排序
+      industryWorkSituationCountDataList.value.sort((a, b) => a.estateCategoryId - b.estateCategoryId);
+      // 统计小计数据
+      calculateCategorySubtotal();
+      // 在末尾添加合计数据
+      industryWorkSituationCountDataList.value.push(count);
+    }).finally(() => {
+      searchLoading.value = false;
+    })
+  }
+}
+
+// 按一级行业名称判断所属产业
+function setEstateCategoryName(newData: any) {
+  // 所属产业判断
+  const categoryMap = {
+    '农、林、牧、渔业': {name: '第一产业', id: 1},
+    '采矿业': {name: '第二产业', id: 2},
+    '制造业': {name: '第二产业', id: 2},
+    '电力、热力、燃气及水生产和供应业': {name: '第二产业', id: 2},
+    '建筑业': {name: '第二产业', id: 2}
+  };
+  if (newData.parentIndustryName && categoryMap[newData.parentIndustryName]) {
+    const category = categoryMap[newData.parentIndustryName];
+    newData.estateCategoryName = category.name;
+    newData.estateCategoryId = category.id;
+  } else {
+    newData.estateCategoryName = '第三产业';
+    newData.estateCategoryId = 3;
+  }
+}
+
+// 统计小计数据
+function calculateCategorySubtotal() {
+  // 初始化每个类别的计数对象
+  const categorySubtotal = {
+    1: {}, // 第一产业
+    2: {}, // 第二产业
+    3: {} // 第三产业
+  };
+  // 初始化字段值为0
+  industryWorkSituationCountKeyTemp.value.forEach((key: any) => {
+    [1, 2, 3].forEach(categoryId => {
+      categorySubtotal[categoryId][key] = 0;
+    });
+  });
+  // 循环统计数据,进行小计数量的累加
+  industryWorkSituationCountDataList.value.forEach((count: any) => {
+    if (categorySubtotal[count.estateCategoryId]) {
+      Object.keys(categorySubtotal[count.estateCategoryId]).forEach(key => {
+        categorySubtotal[count.estateCategoryId][key] += count[key];
+      });
+    }
+  });
+  // 设置文本字段名称
+  ['estateCategoryName', 'parentIndustryName', 'industryName'].forEach((key: any) => {
+    [1, 2, 3].forEach(categoryId => {
+      categorySubtotal[categoryId][key] = '小计';
+    });
+  });
+  // 向表格插入小计数据
+  [1, 2, 3].forEach(categoryId => {
+    const lastIndex = industryWorkSituationCountDataList.value.map(item => item.estateCategoryId).lastIndexOf(categoryId);
+    if (lastIndex !== -1) {
+      industryWorkSituationCountDataList.value.splice(lastIndex + 1, 0, categorySubtotal[categoryId]);
+    }
+  });
+}
+
+
+onMounted(() => {
+  getCompanyModel();
+  onFinish();
+})
+</script>
+
+<style scoped>
+
+</style>

+ 2 - 2
vue/src/views/statistics/SiteStatistics.vue

@@ -136,8 +136,8 @@ const regionList = ref<Array<any>>([]);
 const siteList = ref();
 const searchType = ref("personTypeByJobUser");
 const searchLoading = ref(false);
-const personTypeInRegionKeyTemp = [];
-const personTypeInRegionTableColumns = ref([{
+const personTypeInRegionKeyTemp = new Array<any>([]);
+const personTypeInRegionTableColumns = ref<Array<any>>([{
   title: '人员类别', dataIndex: 'keyTypeName', key: 'keyTypeName', align: "center", width: 280
 },]);
 const personTypeInRegionList = ref<Array<any>>([])