Przeglądaj źródła

feat: 求职人员统计

zhangying 8 miesięcy temu
rodzic
commit
f7cf1f3cd6

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

@@ -0,0 +1,4 @@
+-- 2024-6-17 求职人员统计菜单与权限数据
+INSERT INTO sys_function_code VALUES ('T010504', '求职人员统计', 'T0105', 4);
+INSERT INTO `sys_menu` VALUES ('T010504', 4, '求职人员统计', NULL, 'views/statistics/JobUserCount', '/JobUserCount', 'T0105', NULL, 0, 1, 1, 'T010504', 1, NULL,NULL);
+insert into sys_role_sys_function_code (`RoleID`, `FunctionCode`) values('20afde90-a81a-11ed-a6c5-7085c2a9999e','T010504');

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

@@ -7,6 +7,9 @@ import com.hz.employmentsite.util.DateUtils;
 import com.hz.employmentsite.util.ExcelHelper;
 import com.hz.employmentsite.vo.statistics.RegionSystemDataCount;
 import com.hz.employmentsite.vo.statistics.SystemDataCount;
+import com.hz.employmentsite.vo.statistics.jobUser.AgeRangeJobUserCount;
+import com.hz.employmentsite.vo.statistics.jobUser.PersonTypeJobUserCount;
+import com.hz.employmentsite.vo.statistics.jobUser.RegionJobUserCount;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -55,6 +58,33 @@ public class StatisticsController {
         return RespGenerstor.success(result);
     }
 
+    /**
+     * 查询各个年龄段的求职人员数量
+     */
+    @GetMapping("/jobUserCountByAgeRange")
+    public BaseResponse findJobUserCountByAgeRange() {
+        List<AgeRangeJobUserCount> result = statisticsService.findJobUserCountByAgeRange();
+        return RespGenerstor.success(result);
+    }
+
+    /**
+     * 查询各重点人员类别在各学历的分布情况
+     */
+    @GetMapping("/jobUserCountByPersonType")
+    public BaseResponse findJobUserCountByPersonType() {
+        List<PersonTypeJobUserCount> result = statisticsService.findJobUserCountByPersonType();
+        return RespGenerstor.success(result);
+    }
+
+    /**
+     * 查询各区县的普通失业人员与就业困难人员情况
+     */
+    @GetMapping("/jobUserByRegionAndDifficulty")
+    public BaseResponse findJobUserByRegionAndDifficulty() {
+        List<RegionJobUserCount> result = statisticsService.findJobUserByRegionAndDifficulty();
+        return RespGenerstor.success(result);
+    }
+
     /**
      * 导出指定时间段的系统使用情况
      *

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

@@ -2,6 +2,9 @@ package com.hz.employmentsite.mapper.cquery;
 
 import com.hz.employmentsite.vo.statistics.RegionSystemDataCount;
 import com.hz.employmentsite.vo.statistics.SystemDataCount;
+import com.hz.employmentsite.vo.statistics.jobUser.AgeRangeJobUserCount;
+import com.hz.employmentsite.vo.statistics.jobUser.PersonTypeJobUserCount;
+import com.hz.employmentsite.vo.statistics.jobUser.RegionJobUserCount;
 import org.apache.ibatis.annotations.Param;
 
 import java.time.LocalDate;
@@ -31,4 +34,24 @@ public interface StatisticsCQuery {
      * 查询各区县的驿站工作人员合计数量
      */
     List<Map<String, Object>> findRegionSiteUserCount();
+
+    /**
+     * 查询各年龄段的求职人员数量
+     */
+    List<AgeRangeJobUserCount> findJobUserCountByAgeRange();
+
+    /**
+     * 查询各重点人员类别在各学历的分布情况
+     */
+    List<PersonTypeJobUserCount> findJobUserCountByPersonType();
+
+    /**
+     * 查询各县区的未就业的求职人员清空
+     */
+    List<RegionJobUserCount> findJobUserByRegionAndStatus();
+
+    /**
+     * 查询各县区的就业困难人员情况(特殊重点人员类别)
+     */
+    List<RegionJobUserCount> findJobUserByRegionAndPersonType();
 }

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

@@ -5,6 +5,9 @@ import com.hz.employmentsite.services.service.statistics.StatisticsService;
 import com.hz.employmentsite.util.DateUtils;
 import com.hz.employmentsite.vo.statistics.RegionSystemDataCount;
 import com.hz.employmentsite.vo.statistics.SystemDataCount;
+import com.hz.employmentsite.vo.statistics.jobUser.AgeRangeJobUserCount;
+import com.hz.employmentsite.vo.statistics.jobUser.PersonTypeJobUserCount;
+import com.hz.employmentsite.vo.statistics.jobUser.RegionJobUserCount;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -156,4 +159,82 @@ public class StatisticsServiceImpl implements StatisticsService {
 
         return result;
     }
+
+    /**
+     * 查询各年龄段的求职人员数量
+     */
+    @Override
+    public List<AgeRangeJobUserCount> findJobUserCountByAgeRange() {
+        return statisticsCQuery.findJobUserCountByAgeRange();
+    }
+
+    /**
+     * 查询各重点人员类别在各学历的分布情况
+     */
+    @Override
+    public List<PersonTypeJobUserCount> findJobUserCountByPersonType() {
+        List<PersonTypeJobUserCount> result = statisticsCQuery.findJobUserCountByPersonType();
+
+        // 从 result 中获取到不重复所有的学历ID与名称值
+        Map<Integer, String> cultureRankToNameMap = new HashMap<>();
+        for (PersonTypeJobUserCount record : result) {
+            cultureRankToNameMap.putIfAbsent(record.getCultureRank(), record.getCultureName());
+        }
+
+        // 创建重点人员类别ID到重点人员类别名称和学历列表的映射
+        Map<Integer, String> keyPersonTypeIDToNameMap = new HashMap<>();
+        Map<Integer, Set<Integer>> personTypeIdToCultureRanksMap = new HashMap<>();
+        for (PersonTypeJobUserCount record : result) {
+            keyPersonTypeIDToNameMap.putIfAbsent(record.getKeyPersonTypeID(), record.getKeyTypeName());
+            personTypeIdToCultureRanksMap
+                    .computeIfAbsent(record.getKeyPersonTypeID(), k -> new HashSet<>())
+                    .add(record.getCultureRank());
+        }
+
+        // 遍历所有的重点人员类别ID和学历ID与名称Map的键,检查某个重点人员类别是否缺少某个学历的统计数据
+        for (Map.Entry<Integer, Set<Integer>> entry : personTypeIdToCultureRanksMap.entrySet()) {
+            Integer keyPersonTypeID = entry.getKey();
+            Set<Integer> existingRanks = entry.getValue();
+            String keyTypeName = keyPersonTypeIDToNameMap.get(keyPersonTypeID);
+
+            for (Map.Entry<Integer, String> cultureEntry : cultureRankToNameMap.entrySet()) {
+                Integer cultureRank = cultureEntry.getKey();
+                String cultureName = cultureEntry.getValue();
+                if (!existingRanks.contains(cultureRank)) {
+                    // 插入默认的数据
+                    result.add(new PersonTypeJobUserCount(keyPersonTypeID, keyTypeName, cultureRank, cultureName, 0));
+                }
+            }
+        }
+
+        // 对 result 进行排序:按 keyPersonTypeID 升序,cultureRank 降序
+        result.sort(Comparator.comparing(PersonTypeJobUserCount::getKeyPersonTypeID)
+                .thenComparing(Comparator.comparing(PersonTypeJobUserCount::getCultureRank).reversed()));
+
+        return result;
+    }
+
+    /**
+     * 查询县区的失业人员与就业困难人数情况
+     */
+    @Override
+    public List<RegionJobUserCount> findJobUserByRegionAndDifficulty() {
+        List<RegionJobUserCount> regionCountList = statisticsCQuery.findJobUserByRegionAndStatus();
+        List<RegionJobUserCount> difficultyCountList = statisticsCQuery.findJobUserByRegionAndPersonType();
+
+        // 解析两个查询结果
+        regionCountList.forEach(item -> {
+            // 在difficultyCountList中查找相同regionCode的项目
+            difficultyCountList.stream()
+                    .filter(difficultyItem -> difficultyItem.getRegionCode().equals(item.getRegionCode()))
+                    .findFirst()
+                    .ifPresent(difficultyItem -> {
+                        // 将找到的difficultyItem的jobUserCount赋值给item的difficultyCount
+                        item.setDifficultyCount(difficultyItem.getJobUserCount());
+                    });
+        });
+
+        return regionCountList;
+
+    }
 }

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

@@ -2,6 +2,9 @@ package com.hz.employmentsite.services.service.statistics;
 
 import com.hz.employmentsite.vo.statistics.RegionSystemDataCount;
 import com.hz.employmentsite.vo.statistics.SystemDataCount;
+import com.hz.employmentsite.vo.statistics.jobUser.AgeRangeJobUserCount;
+import com.hz.employmentsite.vo.statistics.jobUser.PersonTypeJobUserCount;
+import com.hz.employmentsite.vo.statistics.jobUser.RegionJobUserCount;
 
 import java.util.Date;
 import java.util.List;
@@ -23,4 +26,19 @@ public interface StatisticsService {
      * @return
      */
     Map<String, List<RegionSystemDataCount>> findMonthSystemDataCount(String dateStr);
+
+    /**
+     * 查询各年龄段的求职人员数量
+     */
+    List<AgeRangeJobUserCount> findJobUserCountByAgeRange();
+
+    /**
+     * 查询各重点人员类别在各学历的分布情况
+     */
+    List<PersonTypeJobUserCount> findJobUserCountByPersonType();
+
+    /**
+     * 查询县区的失业人员与就业困难人数情况
+     */
+    List<RegionJobUserCount> findJobUserByRegionAndDifficulty();
 }

+ 12 - 0
src/main/java/com/hz/employmentsite/vo/statistics/jobUser/AgeRangeJobUserCount.java

@@ -0,0 +1,12 @@
+package com.hz.employmentsite.vo.statistics.jobUser;
+
+import lombok.Data;
+
+@Data
+public class AgeRangeJobUserCount {
+    private String ageRange;
+
+    private Integer sex;
+
+    private int jobUserCount;
+}

+ 20 - 0
src/main/java/com/hz/employmentsite/vo/statistics/jobUser/PersonTypeJobUserCount.java

@@ -0,0 +1,20 @@
+package com.hz.employmentsite.vo.statistics.jobUser;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class PersonTypeJobUserCount {
+    private Integer keyPersonTypeID;
+
+    private String keyTypeName;
+
+    private Integer cultureRank;
+
+    private String cultureName;
+
+    private int jobUserCount;
+}

+ 20 - 0
src/main/java/com/hz/employmentsite/vo/statistics/jobUser/RegionJobUserCount.java

@@ -0,0 +1,20 @@
+package com.hz.employmentsite.vo.statistics.jobUser;
+
+import lombok.Data;
+
+@Data
+public class RegionJobUserCount {
+    private String regionCode;
+
+    private String regionName;
+
+    /**
+     * 正常失业人数
+     */
+    private int jobUserCount;
+
+    /**
+     * 就业困难人数
+     */
+    private int difficultyCount;
+}

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

@@ -148,4 +148,83 @@
         ORDER BY
             area.`code`
     </select>
+
+    <select id="findJobUserCountByAgeRange" resultType="com.hz.employmentsite.vo.statistics.jobUser.AgeRangeJobUserCount">
+        SELECT
+            CASE
+                WHEN TIMESTAMPDIFF(YEAR, BirthDay, CURDATE()) BETWEEN 16 AND 25 THEN '16-25岁'
+                WHEN TIMESTAMPDIFF(YEAR, BirthDay, CURDATE()) BETWEEN 26 AND 35 THEN '26-35岁'
+                WHEN TIMESTAMPDIFF(YEAR, BirthDay, CURDATE()) BETWEEN 36 AND 45 THEN '36-45岁'
+                WHEN TIMESTAMPDIFF(YEAR, BirthDay, CURDATE()) BETWEEN 46 AND 55 THEN '46-55岁'
+                ELSE '55岁以上'
+                END AS AgeRange,
+            Sex,
+            COUNT(1) AS jobUserCount
+        FROM
+            pc_jobuser
+        GROUP BY
+            AgeRange,
+            Sex
+        ORDER BY
+            AgeRange,
+            Sex;
+    </select>
+
+    <select id="findJobUserCountByPersonType" resultType="com.hz.employmentsite.vo.statistics.jobUser.PersonTypeJobUserCount">
+        SELECT
+            jobuser.KeyPersonTypeID,
+            keytype.`Name` AS KeyTypeName,
+            jobuser.CultureRank,
+            culture.`Name` AS CultureName,
+            COUNT( 1 ) AS jobUserCount
+        FROM
+            `pc_jobuser` jobuser
+                LEFT JOIN sys_dictionary_item keytype ON jobuser.KeyPersonTypeID = keytype.`Value`
+                AND keytype.DictionaryCode = 'KeyPersonType'
+                LEFT JOIN sys_dictionary_item culture ON jobuser.CultureRank = culture.`Value`
+                AND culture.DictionaryCode = 'HighestDegree'
+        WHERE
+            CultureRank IS NOT NULL
+        GROUP BY
+            jobuser.KeyPersonTypeID,
+            KeyTypeName,
+            jobuser.CultureRank
+        ORDER BY
+            jobuser.KeyPersonTypeID,
+            jobuser.CultureRank DESC
+    </select>
+
+    <select id="findJobUserByRegionAndStatus" resultType="com.hz.employmentsite.vo.statistics.jobUser.RegionJobUserCount">
+        SELECT
+            site.RegionCode,
+            area.`name` AS RegionName,
+            COUNT(1) AS jobUserCount
+        FROM
+            pc_jobuser jobUser
+                LEFT JOIN pc_site site ON jobUser.SiteID = site.SiteID
+                LEFT JOIN area_code area ON site.RegionCode = area.`code`
+        GROUP BY
+            site.RegionCode,
+            RegionName
+        ORDER BY
+            site.RegionCode
+    </select>
+
+    <select id="findJobUserByRegionAndPersonType" resultType="com.hz.employmentsite.vo.statistics.jobUser.RegionJobUserCount">
+        SELECT
+            site.RegionCode,
+            area.`name` AS RegionName,
+            COUNT(1) AS jobUserCount
+        FROM
+            pc_jobuser jobUser
+                LEFT JOIN pc_site site ON jobUser.SiteID = site.SiteID
+                LEFT JOIN area_code area ON site.RegionCode = area.`code`
+        WHERE
+                jobUser.KeyPersonTypeID IN (13,14,15,16,17,18,19,20,21,22,23,24)
+        GROUP BY
+            site.RegionCode,
+            RegionName
+        ORDER BY
+            site.RegionCode
+    </select>
 </mapper>

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

@@ -33,3 +33,51 @@ export function getMonthSystemDataCount(params: any) {
     },
   );
 }
+
+/**
+ * 查询各个年龄段的求职人员数量
+ */
+export function getJobUserCountByAgeRange() {
+  return request<object>(
+    {
+      url: 'statistics/jobUserCountByAgeRange',
+      method: 'get',
+      params: {},
+    },
+    {
+      isNew: true,
+    },
+  );
+}
+
+/**
+ * 查询各重点人员类别在各学历的分布情况
+ */
+export function getJobUserCountByPersonType() {
+  return request<object>(
+    {
+      url: 'statistics/jobUserCountByPersonType',
+      method: 'get',
+      params: {},
+    },
+    {
+      isNew: true,
+    },
+  );
+}
+
+/**
+ * 查询各区县的普通失业人员与就业困难人员情况
+ */
+export function getJobUserByRegionAndDifficulty() {
+  return request<object>(
+    {
+      url: 'statistics/jobUserByRegionAndDifficulty',
+      method: 'get',
+      params: {},
+    },
+    {
+      isNew: true,
+    },
+  );
+}

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

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

+ 93 - 6
vue/src/utils/echartsUtil.ts

@@ -10,9 +10,7 @@ import * as echarts from 'echarts';
 export function initBarImageTable(xTitleList: any, yValueList: any, domId: any, title: string) {
   const chartDom = document.getElementById(domId);
   const myChart = echarts.init(chartDom);
-  let option;
-
-  option = {
+  let option = {
     title: {
       text: title,
     },
@@ -51,6 +49,97 @@ export function initBarImageTable(xTitleList: any, yValueList: any, domId: any,
   option && myChart.setOption(option);
 }
 
+/**
+ * 堆叠柱状图表初始化
+ * @param xTitleList X轴数据
+ * @param seriesList 图表数据内容-包含堆叠数据
+ * @param legendList 图表数据说明
+ * @param domId 目标DOM元素ID
+ * @param title 图表标题
+ */
+export function initStackBarImageTable(xTitleList: any, seriesList: any, legendList: any, domId: any, title: string) {
+  const chartDom = document.getElementById(domId);
+  const myChart = echarts.init(chartDom);
+  let option = {
+    title: {
+      text: title,
+    },
+    toolbox: {
+      feature: {
+        saveAsImage: {}
+      }
+    },
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    legend: {
+      data: legendList
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      data: xTitleList
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: seriesList
+  };
+
+  option && myChart.setOption(option);
+}
+
+/**
+ * 数据集柱状图表初始化
+ * @param dataSetSource 数据集数据
+ * @param seriesList 柱形图表样式定义
+ * @param domId 目标DOM元素ID
+ * @param title 图表标题
+ */
+export function initDataSetBarImageTable(dataSetSource: any, seriesList: any, domId: any, title: string) {
+  const chartDom = document.getElementById(domId);
+  const myChart = echarts.init(chartDom);
+  let option = {
+    title: {
+      text: title,
+    },
+    toolbox: {
+      feature: {
+        saveAsImage: {}
+      }
+    },
+    legend: {},
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: {
+        type: 'shadow'
+      }
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '3%',
+      containLabel: true
+    },
+    dataset: {
+      source: dataSetSource
+    },
+    xAxis: {type: 'category'},
+    yAxis: {},
+    series: seriesList
+  };
+
+  option && myChart.setOption(option);
+}
+
 /**
  * 折线图表初始化
  * @param xTitleList X轴标题数据
@@ -61,9 +150,7 @@ export function initBarImageTable(xTitleList: any, yValueList: any, domId: any,
 export function initLineImageTable(xTitleList: any, seriesList: any, domId: any, title: string) {
   const chartDom = document.getElementById(domId);
   const myChart = echarts.init(chartDom);
-  let option;
-
-  option = {
+  let option = {
     title: {
       text: title
     },

+ 316 - 0
vue/src/views/statistics/JobUserCount.vue

@@ -0,0 +1,316 @@
+<template>
+  <div class="card-search">
+    <!-- 操作按钮 -->
+    <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="ageRange">各年龄段人员分布</a-radio-button>
+            <a-radio-button value="personTypeAndCulture">重点人员类别与学历分布</a-radio-button>
+            <a-radio-button value="regionAndDifficulty">各区县就业困难人员数量</a-radio-button>
+          </a-radio-group>
+        </div>
+        <div>
+        </div>
+      </a-col>
+    </a-row>
+    <!-- 数据展示 -->
+    <!-- 年龄段统计 -->
+    <div v-show="searchType == 'ageRange'">
+      <a-divider orientation="left">表格</a-divider>
+      <a-table :columns="ageRangeTableColumns" :data-source="ageRangeJobUserData.tableList" :scroll="{ x:'100%' }"
+               :loading="searchLoading"
+               :pagination="false"
+               bordered>
+      </a-table>
+      <a-divider orientation="left">图表</a-divider>
+      <div id="ageRangeImageTable" style="width: 100%; height: 500px"></div>
+    </div>
+    <!-- 重点人员类别-学历分布统计 -->
+    <div v-show="searchType == 'personTypeAndCulture'">
+      <a-divider orientation="left">表格</a-divider>
+      <a-table :columns="personTypeTableColumns" :data-source="personTypeJobUserData.tableList" :scroll="{ x:'100%' }"
+               :loading="searchLoading"
+               :pagination="false"
+               bordered>
+      </a-table>
+      <a-divider orientation="left">图表</a-divider>
+      <div id="personTypeAndCultureImageTable" style="width: 100%; height: 500px"></div>
+    </div>
+    <!-- 正常失业人员与就业困难人员统计 -->
+    <div v-show="searchType == 'regionAndDifficulty'">
+      <a-divider orientation="left">表格</a-divider>
+      <a-table :columns="regionTableColumns" :data-source="regionJobUserData.tableList" :scroll="{ x:'100%' }"
+               :loading="searchLoading"
+               :pagination="false"
+               bordered>
+      </a-table>
+      <a-divider orientation="left">图表</a-divider>
+      <div id="regionAndDifficultyImageTable" style="width: 100%; height: 500px"></div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {onMounted, reactive, ref} from "vue";
+import {
+  getJobUserByRegionAndDifficulty,
+  getJobUserCountByAgeRange,
+  getJobUserCountByPersonType
+} from "@/api/statistics";
+import {initDataSetBarImageTable, initStackBarImageTable} from "@/utils/echartsUtil";
+
+// 查询方法类型
+const searchType = ref("ageRange");
+// 查询加载
+const searchLoading = ref(false);
+
+// 各年龄段人员统计数据
+const ageRangeJobUserData = reactive({
+  originalList: new Array<any>(),
+  tableList: new Array<any>(),
+  imageTable: new Array<any>(),
+})
+// 各年龄段人员统计数据表格定义
+const ageRangeTableColumns = [
+  {
+    title: '年龄段', dataIndex: 'ageRange', key: 'ageRange', align: "center"
+  },
+  {
+    title: '男', dataIndex: 'maleCount', key: 'maleCount', align: "center"
+  },
+  {
+    title: '女', dataIndex: 'femaleCount', key: 'femaleCount', align: "center"
+  },
+  {
+    title: '合计', dataIndex: 'total', key: 'total', align: "center"
+  },
+]
+// 各重点人员在各学历分布统计数据
+const personTypeJobUserData = reactive({
+  originalList: new Array<any>(),
+  tableList: new Array<any>(),
+  imageTable: new Array<any>(),
+});
+// 各重点人员在各学历分布统计数据表格定义
+const personTypeTableColumns = ref([
+  {
+    title: '人员类别', dataIndex: 'keyTypeName', key: 'keyTypeName', align: "center"
+  },
+])
+// 各区县的失业人数与就业困难人数统计数据
+const regionJobUserData = reactive({
+  originalList: new Array<any>(),
+  tableList: new Array<any>(),
+  imageTable: new Array<any>(),
+});
+// 各区县的失业人数与就业困难人数统计数据表格定义
+const regionTableColumns = [
+  {
+    title: '县区', dataIndex: 'regionName', key: 'regionName', align: "center"
+  },
+  {
+    title: '失业人员数量', dataIndex: 'jobUserCount', key: 'jobUserCount', align: "center"
+  },
+  {
+    title: '就业困难人数', dataIndex: 'difficultyCount', key: 'keyTypeName', align: "center"
+  },
+]
+
+// 查询各年龄段求职人员数量
+async function ageRangeOnSearch() {
+  searchLoading.value = true;
+  await getJobUserCountByAgeRange().then((result: any) => {
+    // 保存原始数据
+    ageRangeJobUserData.originalList = result;
+
+    // 生成表格数据
+    let tableList: any[] = [];
+    let ageRangeMap: { [key: string]: any } = {};
+    let imageTableMaleCount: number[] = [];
+    let imageTableFemaleCount: number[] = [];
+
+    result.forEach((resultItem: any) => {
+      let {ageRange, sex, jobUserCount} = resultItem;
+
+      // 如果 ageRangeMap 中不存在该年龄段,初始化
+      if (!ageRangeMap[ageRange]) {
+        ageRangeMap[ageRange] = {ageRange, maleCount: 0, femaleCount: 0};
+        tableList.push(ageRangeMap[ageRange]);
+      }
+
+      // 根据性别累加对应的计数,并记录到图表数据数组中
+      if (sex === 1) {
+        ageRangeMap[ageRange].maleCount += jobUserCount;
+        imageTableMaleCount.push(jobUserCount);
+      } else if (sex === 2) {
+        ageRangeMap[ageRange].femaleCount += jobUserCount;
+        imageTableFemaleCount.push(jobUserCount);
+      }
+
+      // 计算总计数
+      ageRangeMap[ageRange].total = ageRangeMap[ageRange].maleCount + ageRangeMap[ageRange].femaleCount;
+    });
+
+    // 计算合计
+    let maleCount = 0, femaleCount = 0;
+    tableList.forEach(item => {
+      maleCount += item.maleCount;
+      femaleCount += item.femaleCount;
+    });
+
+    // 将合计数据添加到
+    tableList.push({ageRange: '合计', maleCount, femaleCount, total: maleCount + femaleCount});
+    ageRangeJobUserData.tableList = tableList;
+
+    // 创建图表数据
+    let bars = ['男', '女'].map((name, index) => ({
+      name,
+      type: 'bar',
+      stack: 'ageRange',
+      emphasis: {focus: 'series'},
+      data: index == 0 ? imageTableMaleCount : imageTableFemaleCount
+    }));
+
+    // 生成图表
+    setTimeout(() => {
+      initStackBarImageTable(['16-25岁', '26-35岁', '36-45岁', '46-55岁', '55岁以上'], bars, ['男', '女'], 'ageRangeImageTable', '各年龄段求职人员数量')
+    }, 100)
+
+  }).finally(() => {
+    searchLoading.value = false;
+  })
+}
+
+// 查询各重点人员类别在各学历的分布情况
+async function personTypeOnSearch() {
+  searchLoading.value = true;
+  await getJobUserCountByPersonType().then((result: any) => {
+    // 保存原始数据
+    personTypeJobUserData.originalList = result;
+
+    // 表格数据
+    let tableList: any[] = [];
+    // 初始化表格定义
+    personTypeTableColumns.value = [
+      {
+        title: '人员类别', dataIndex: 'keyTypeName', key: 'keyTypeName', align: "center"
+      },
+    ];
+    // 表格title与key的键值对
+    let tableKeyAndName = new Map();
+
+    // 解析准备生成表格数据
+    result.forEach((resultItem: any) => {
+      tableKeyAndName.set(resultItem.cultureRank, resultItem.cultureName);
+      // 创建对象字段名称
+      const key = 'cultureRank' + resultItem.cultureRank;
+
+      // 查询相同的KeyPersonTypeID的对应数组下标
+      const findIndex = tableList.findIndex(item => item.keyPersonTypeID == resultItem.keyPersonTypeID);
+      if (findIndex != -1) {
+        // 在已添加的元素里进行数据插入
+        tableList[findIndex][key] = resultItem.jobUserCount;
+      } else {
+        // 创建一个新的元素
+        let data = {
+          keyPersonTypeID: resultItem.keyPersonTypeID,
+          keyTypeName: resultItem.keyTypeName
+        }
+        data[key] = resultItem.jobUserCount;
+        tableList.push(data)
+      }
+    })
+    // 填充表结构
+    tableKeyAndName.forEach((value: any, key: any) => {
+      personTypeTableColumns.value.push({
+        title: value, dataIndex: 'cultureRank' + key, key: 'cultureRank' + key, align: "center"
+      })
+    })
+    personTypeJobUserData.tableList = tableList;
+
+    // 创建图表数据
+    // X轴标题内容
+    const xTitleList = tableList.map(item => item.keyTypeName);
+    // Y轴的值内容
+    const yValueList = result.reduce((acc: any, item: any) => {
+      if (!acc[item.cultureName]) {
+        acc[item.cultureName] = [];
+      }
+      // 将人数填充
+      acc[item.cultureName].push(item.jobUserCount);
+      return acc;
+    }, {});
+    let bars: any[] = [];
+    let legendList: any[] = [];
+    for (let key in yValueList) {
+      legendList.push(key);
+      bars.push({
+        name: key,
+        type: 'bar',
+        stack: 'ageRange',
+        emphasis: {focus: 'series'},
+        data: yValueList[key]
+      })
+    }
+
+    // 生成图表
+    setTimeout(() => {
+      initStackBarImageTable(xTitleList, bars, legendList, 'personTypeAndCultureImageTable', '重点人员类别学历分布统计')
+    }, 100)
+  }).finally(() => {
+    searchLoading.value = false;
+  })
+}
+
+// 查询各区县正常失业人员与就业困难人员情况
+async function regionDifficultyOnSearch() {
+  searchLoading.value = true;
+  await getJobUserByRegionAndDifficulty().then((result: any) => {
+    // 保存原始数据
+    regionJobUserData.originalList = result;
+    regionJobUserData.tableList = result;
+
+    let arr: any[] = [];
+    arr.push(['类型', '失业人数', '就业困难人数'])
+    result.forEach((item: any) => {
+      arr.push([item.regionName, item.jobUserCount, item.difficultyCount])
+    })
+    
+    // 生成表格
+    setTimeout(() => {
+      initDataSetBarImageTable(arr, [{type: 'bar'}, {type: 'bar'}], 'regionAndDifficultyImageTable', '各区县失业人员与就业困难人员情况统计')
+    }, 100)
+  }).finally(() => {
+    searchLoading.value = false;
+  })
+}
+
+// 查询方法变更事件
+function searchTypeChange() {
+  if (searchType.value == 'ageRange') {
+    ageRangeOnSearch();
+  }
+  if (searchType.value == 'personTypeAndCulture') {
+    personTypeOnSearch();
+  }
+  if (searchType.value == 'regionAndDifficulty') {
+    regionDifficultyOnSearch();
+  }
+}
+
+onMounted(() => {
+  searchTypeChange();
+})
+</script>
+
+<script lang="ts">
+// 设置页面名称进行组件缓存
+export default {
+  name: "JobUserCount",
+}
+</script>
+
+<style scoped>
+
+</style>

+ 3 - 1
vue/src/views/statistics/MonthSystemApplyCount.vue

@@ -282,7 +282,9 @@ function dataTypeChange() {
     analysisByTable();
   }
   if (dataType.value == 'imageTable') {
-    nextTick(analysisByImageTable);
+    setTimeout(() => {
+      analysisByImageTable();
+    }, 100);
   }
 }