Files
shz-backend/docs/cms-statistics-api.md

770 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 统计分析接口文档
本文档面向 PC 管理端前端,覆盖业务统计、招聘会统计、求职统计、热门岗位统计和用人单位统计。
## 1. 通用约定
### 1.1 基础路径
```text
/cms
```
以下接口均为后台管理接口,实际请求时需要按项目现有登录机制携带登录态/Token。
### 1.2 响应包装
接口统一使用项目的 `AjaxResult` 响应包装,前端通常从 `data` 读取业务数据:
```json
{
"code": 200,
"msg": "操作成功",
"data": {}
}
```
### 1.3 统计时间参数
`/cms/statics/*` 统计接口使用以下参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `startDate` | string | 否 | 开始日期,支持 `yyyy-MM-dd``yyyy-MM` |
| `endDate` | string | 否 | 结束日期,支持 `yyyy-MM-dd``yyyy-MM` |
| `startTime` | string | 否 | `startDate` 的兼容参数名 |
| `endTime` | string | 否 | `endDate` 的兼容参数名 |
时间规则:
- 不传开始时间时,默认从当前年度 `1 月 1 日` 开始。
- 不传结束时间时,默认到当前日期结束。
- 传入 `yyyy-MM` 时,开始月份按当月 1 日处理,结束月份按当月最后一天处理。
- 查询时间采用左闭右开区间,结束日期当天的数据会被包含。
- `startDate``endDate` 不能颠倒。
示例:
```http
GET /cms/statics/business?startDate=2026-01-01&endDate=2026-06-30
```
## 2. 业务统计
### 2.1 接口信息
```http
GET /cms/statics/business
```
### 2.2 统计口径
返回按月统计的数据:
- 岗位来源:从 `job` 表统计 `data_source`
- 本地石河子模板导入:`data_source = '5'`
- 本地录入:`data_source = '1'`
- 互联网岗位上传:`data_source = '2'`
- 新增注册人数:从 `app_user` 表按 `create_time` 统计。
岗位和用户均只统计 `del_flag = '0'` 的数据。
### 2.3 返回结构
```json
{
"months": [
"2026-01",
"2026-02",
"2026-03"
],
"jobSourceSeries": [
{
"code": "5",
"name": "本地石河子模板导入",
"data": [12, 18, 21]
},
{
"code": "1",
"name": "本地录入",
"data": [8, 10, 13]
},
{
"code": "2",
"name": "互联网岗位上传",
"data": [35, 42, 50]
}
],
"newRegisterSeries": {
"code": "register",
"name": "新增注册人数",
"data": [20, 31, 46]
}
}
```
### 2.4 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| `months` | string[] | 横坐标月份,格式为 `yyyy-MM` |
| `jobSourceSeries` | object[] | 三种岗位来源序列 |
| `jobSourceSeries[].code` | string | 来源编码:`5``1``2` |
| `jobSourceSeries[].name` | string | 来源名称 |
| `jobSourceSeries[].data` | number[] | 与 `months` 按下标一一对应 |
| `newRegisterSeries` | object | 新增注册人数序列 |
| `newRegisterSeries.data` | number[] | 与 `months` 按下标一一对应 |
### 2.5 前端图表建议
- 折线图或柱状图横轴使用 `months`
- `jobSourceSeries` 可以绘制三条岗位来源曲线。
- `newRegisterSeries` 单独绘制新增注册人数曲线,或作为第二个图表的数据源。
## 3. 招聘会统计
### 3.1 接口信息
```http
GET /cms/outdoor-fair/statistics
```
### 3.2 请求参数
| 参数 | 类型 | 必填 | 可选值/说明 |
|---|---|---:|---|
| `granularity` | string | 否 | `day``week``month``quarter``year`,默认 `month` |
| `startTime` | string | 否 | 格式为 `yyyy-MM-dd HH:mm:ss` |
| `endTime` | string | 否 | 格式为 `yyyy-MM-dd HH:mm:ss` |
示例:
```http
GET /cms/outdoor-fair/statistics?granularity=quarter&startTime=2026-01-01%2000:00:00&endTime=2026-12-31%2023:59:59
```
### 3.3 时间规则
- `granularity=day`:按天统计。
- `granularity=week`:按周一作为一周开始统计。
- `granularity=month`:按月统计,默认值。
- `granularity=quarter`按季度统计Q1 为 1-3 月Q2 为 4-6 月Q3 为 7-9 月Q4 为 10-12 月。
- `granularity=year`:按年统计。
- 不传任何时间参数时,累计统计全部招聘会,曲线时间范围根据招聘会实际举办时间的最小值和最大值生成。
- 只传 `endTime` 时,默认向前推 12 个月作为开始范围。
- 只传 `startTime` 时,结束时间默认为当前日期。
### 3.4 返回结构
```json
{
"granularity": "quarter",
"totals": {
"fairCount": 12,
"companyCount": 86,
"jobCount": 430
},
"yoy": {
"fairCount": 12,
"previousFairCount": 9,
"rate": 0.3333333333
},
"mom": {
"fairCount": 12,
"previousFairCount": 10,
"rate": 0.2
},
"series": [
{
"time": "2026-Q1",
"fairCount": 3,
"companyCount": 20,
"jobCount": 105
},
{
"time": "2026-Q2",
"fairCount": 4,
"companyCount": 28,
"jobCount": 140
}
]
}
```
### 3.5 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| `granularity` | string | 实际使用的统计粒度 |
| `totals.fairCount` | number | 区间内招聘会数量 |
| `totals.companyCount` | number | 区间内参会单位数量 |
| `totals.jobCount` | number | 区间内招聘会岗位数量 |
| `yoy.fairCount` | number | 当前区间招聘会数量 |
| `yoy.previousFairCount` | number | 去年同期招聘会数量 |
| `yoy.rate` | number/null | 同比变化率,前值为 0 时返回 `null` |
| `mom.fairCount` | number | 当前区间招聘会数量 |
| `mom.previousFairCount` | number | 上一个等长区间招聘会数量 |
| `mom.rate` | number/null | 环比变化率,前值为 0 时返回 `null` |
| `series` | object[] | 各时间桶的曲线数据 |
| `series[].time` | string | 时间桶名称 |
| `series[].fairCount` | number | 当前时间桶招聘会数量 |
| `series[].companyCount` | number | 当前时间桶参会单位数量 |
| `series[].jobCount` | number | 当前时间桶岗位数量 |
时间桶格式:
| 粒度 | `series[].time` 格式 | 示例 |
|---|---|---|
| `day` | `yyyy-MM-dd` | `2026-07-30` |
| `week` | `yyyy-Www` | `2026-W31` |
| `month` | `yyyy-MM` | `2026-07` |
| `quarter` | `yyyy-Qn` | `2026-Q3` |
| `year` | `yyyy` | `2026` |
同比、环比的 `rate` 是小数,不是百分数字符串。前端展示百分比时可乘以 100 后保留两位小数,例如 `0.3333` 展示为 `33.33%`
## 4. 求职统计
### 4.1 接口信息
```http
GET /cms/statics/jobSeeker
```
### 4.2 统计口径
只统计求职者:
```text
app_user.is_company_user = '1'
```
时间按 `app_user.create_time` 过滤。
统计维度:
- 年龄:`app_user.age`,使用 `dict_type='age'` 字典翻译名称。
- 工作经验:`app_user.work_experience`,使用 `dict_type='experience'` 字典翻译名称。
- 专业/求职方向:解析 `app_user.job_title_id`,关联 `job_title` 获取岗位名称。
### 4.3 返回结构
```json
{
"total": 156,
"age": [
{
"code": "18-25",
"label": "18-25岁",
"count": 58
},
{
"code": "26-35",
"label": "26-35岁",
"count": 72
}
],
"workExperience": [
{
"code": "0",
"label": "无经验",
"count": 40
},
{
"code": "1-3",
"label": "1-3年",
"count": 63
}
],
"profession": [
{
"code": "101",
"label": "行政管理",
"count": 25
},
{
"code": "102",
"label": "销售",
"count": 31
}
]
}
```
### 4.4 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| `total` | number | 时间范围内求职者总数 |
| `age` | object[] | 年龄分组统计 |
| `workExperience` | object[] | 工作经验分组统计 |
| `profession` | object[] | 专业/期望岗位统计 |
| `*.code` | string | 字典值或岗位 ID |
| `*.label` | string | 前端显示名称 |
| `*.count` | number | 该分组人数 |
求职者选择多个期望岗位时,会分别计入多个专业/求职方向分组;因此 `profession` 各项之和可能大于 `total`
### 4.5 前端图表建议
- `age` 使用饼图或柱状图。
- `workExperience` 使用饼图或柱状图。
- `profession` 使用横向柱状图,岗位较多时建议按数量倒序显示 Top N。
## 5. 热门岗位统计
### 5.1 接口信息
```http
GET /cms/statics/hotJob
```
### 5.2 统计口径
热门岗位名称来自业务字典数据表:
```sql
bussiness_dict_data.dict_type = 'job_hot'
```
使用字典项的 `dict_label` 作为热门岗位名称,再按岗位名称前缀匹配 `job.job_title`
```sql
TRIM(job.job_title) LIKE TRIM(dict_label) || '%'
```
例如字典中配置 `洗碗工`,会匹配:
```text
洗碗工
洗碗工杂工
洗碗工服务员
洗碗工(包吃住)
```
只统计 `job.del_flag = '0'` 的岗位,并按 `job.create_time` 过滤时间范围。
### 5.3 返回结构
```json
{
"items": [
{
"code": "wash_worker",
"name": "洗碗工",
"jobCount": 8
},
{
"code": "sales",
"name": "销售",
"jobCount": 32
}
]
}
```
### 5.4 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| `items` | object[] | 热门岗位统计列表 |
| `items[].code` | string | 字典 `dict_value` |
| `items[].name` | string | 字典 `dict_label`,前端图表显示名称 |
| `items[].jobCount` | number | 匹配到的岗位数量 |
字典中已经配置但时间范围内没有匹配岗位的热门岗位也会返回,`jobCount``0`,便于图表保持固定分类顺序。
### 5.5 前端图表建议
```javascript
const categories = data.items.map(item => item.name)
const values = data.items.map(item => item.jobCount)
```
建议使用柱状图或横向柱状图展示热门岗位数量。
## 6. 用人单位统计
### 6.1 接口信息
```http
GET /cms/statics/company
```
### 6.2 统计内容
接口返回两组统计:
- `scale`:按企业规模统计单位数量和发布岗位数量。
- `nature`:按企业性质统计单位数量和发布岗位数量。
单位数量按 `company.create_time` 过滤;发布岗位数量按 `job.create_time` 过滤。这样历史企业在查询时间范围内发布新岗位时,岗位数量仍然可以被统计。
有效单位条件:
```text
company.del_flag = '0'
company.status = 1
company.company_status = '0'
```
有效发布岗位条件:
```text
job.del_flag = '0'
job.is_publish = 1
job.job_status = '0'
job.review_status = '1'
```
### 6.3 企业规模分类
`dict_type='scale'` 的字典值读取企业规模,并按以下规则归并:
| 字典值 | 返回编码 | 返回名称 |
|---|---|---|
| `1` | `1` | 微型 |
| `2` | `2` | 小型 |
| `3` | `3` | 中型 |
| `4、5` | `4_5` | 大型 |
| `6、7` | `6_7` | 超大型 |
例如 `4``5` 的企业都会汇总到 `大型`,对应的 `jobCount` 也会合并统计。
### 6.4 企业性质分类
`dict_type='company_nature'` 且状态正常的字典数据读取企业性质,并使用字典 `dict_value` 匹配:
```text
company.company_nature
```
如果当前字典中只配置了国企,则 `nature` 只返回国企;如果后续新增规上企业等字典项,接口会自动返回新增分类。
### 6.5 返回结构
```json
{
"scale": [
{
"code": "1",
"name": "微型",
"companyCount": 3,
"jobCount": 5
},
{
"code": "2",
"name": "小型",
"companyCount": 20,
"jobCount": 46
},
{
"code": "3",
"name": "中型",
"companyCount": 8,
"jobCount": 31
},
{
"code": "4_5",
"name": "大型",
"companyCount": 4,
"jobCount": 22
},
{
"code": "6_7",
"name": "超大型",
"companyCount": 1,
"jobCount": 12
}
],
"nature": [
{
"code": "1",
"name": "国企",
"companyCount": 5,
"jobCount": 18
}
]
}
```
### 6.6 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| `scale` | object[] | 企业规模统计列表 |
| `nature` | object[] | 企业性质统计列表 |
| `*.code` | string | 统计分类编码 |
| `*.name` | string | 前端显示名称 |
| `*.companyCount` | number | 该分类下单位数量 |
| `*.jobCount` | number | 该分类下有效发布岗位数量 |
### 6.7 前端图表建议
可以按 `scale``nature` 各绘制一个双系列柱状图:
```javascript
const categories = data.scale.map(item => item.name)
const companyData = data.scale.map(item => item.companyCount)
const jobData = data.scale.map(item => item.jobCount)
```
系列名称建议:
```text
单位数量
发布岗位数量
```
## 7. 区划企业分析
### 7.1 接口信息
```http
GET /cms/areaAnalysis/company
```
### 7.2 请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `areaCode` | string | 否 | 区划字典值,不传时查询师市整体 |
| `startDate` | string | 否 | 开始日期,格式 `yyyy-MM-dd` |
| `endDate` | string | 否 | 结束日期,格式 `yyyy-MM-dd` |
`areaCode` 使用业务字典 `dict_type='area'``dict_value`,前端不需要直接传 `sys_area.code`。例如区划选择器应使用区域字典接口返回的 `dict_value` 作为请求参数。
### 7.3 统计口径
企业统计条件:
```text
company.del_flag = '0'
company.status = 1
company.company_status = '0'
```
统计内容:
- 单位总数。
- 按行业统计单位数量。
- 按企业规模统计单位数量,名称使用 `scale` 字典翻译。
- 按企业性质统计单位数量,名称使用 `company_nature` 字典翻译。
### 7.4 返回结构
```json
{
"areaCode": "659001000000",
"areaName": "石河子市",
"totalCompanyCount": 120,
"byIndustry": {
"制造业": 35,
"批发和零售业": 28
},
"byScale": {
"小型": 60,
"中型": 42,
"大型": 18
},
"byNature": {
"国企": 12
}
}
```
### 7.5 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| `areaCode` | string | 实际统计区域编码 |
| `areaName` | string | 实际统计区域名称 |
| `totalCompanyCount` | number | 有效单位总数 |
| `byIndustry` | object | 行业名称到单位数量的映射 |
| `byScale` | object | 企业规模名称到单位数量的映射 |
| `byNature` | object | 企业性质名称到单位数量的映射 |
对象类型字段的 key 为图表显示名称value 为数量。例如:
```javascript
const categories = Object.keys(data.byScale)
const values = Object.values(data.byScale)
```
## 8. 区划岗位分析
### 8.1 接口信息
```http
GET /cms/areaAnalysis/job
```
### 8.2 请求参数
参数与企业分析相同:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `areaCode` | string | 否 | `area` 字典的 `dict_value`,不传查询师市整体 |
| `startDate` | string | 否 | 格式 `yyyy-MM-dd` |
| `endDate` | string | 否 | 格式 `yyyy-MM-dd` |
### 8.3 统计口径
岗位统计条件:
```text
job.del_flag = '0'
job.is_publish = 1
job.job_status = '0'
job.review_status = '1'
```
统计内容:
- 岗位总数。
- 招聘总人数。
- 急招岗位数量。
- 重点人群岗位数量。
- 按岗位分类统计。
- 按薪资区间统计。
- 按学历要求统计。
- 按岗位类型统计。
岗位数量统计使用有效发布岗位。招聘总人数中,岗位 `vacancies` 为空或小于等于 0 时按 1 人计算。
### 8.4 返回结构
```json
{
"areaCode": "659001000000",
"areaName": "石河子市",
"totalJobCount": 360,
"totalVacancies": 780,
"urgentJobCount": 48,
"keyPopulationJobCount": 22,
"byCategory": {
"销售": 80,
"餐饮服务": 55
},
"bySalary": {
"3k以下": 30,
"3k-5k": 120,
"5k-8k": 150,
"8k-15k": 48,
"15k+": 12
},
"byEducation": {
"不限": 180,
"大专": 110,
"本科": 70
},
"byType": {
"全职": 300,
"兼职": 60
}
}
```
### 8.5 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| `areaCode` | string | 实际统计区域编码 |
| `areaName` | string | 实际统计区域名称 |
| `totalJobCount` | number | 有效发布岗位总数 |
| `totalVacancies` | number | 招聘总人数,空值/非正数岗位按 1 人计算 |
| `urgentJobCount` | number | `is_urgent = 1` 的岗位数量 |
| `keyPopulationJobCount` | number | `is_key_populations = '0'` 的岗位数量 |
| `byCategory` | object | 岗位分类到岗位数量的映射 |
| `bySalary` | object | 薪资区间到岗位数量的映射 |
| `byEducation` | object | 学历名称到岗位数量的映射 |
| `byType` | object | 岗位类型名称到岗位数量的映射 |
薪资区间固定为:
```text
3k以下、3k-5k、5k-8k、8k-15k、15k+
```
## 9. 区划就业分析
### 9.1 接口信息
```http
GET /cms/areaAnalysis/employment
```
### 9.2 请求参数
参数与企业分析、岗位分析相同:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| `areaCode` | string | 否 | `area` 字典的 `dict_value`,不传查询师市整体 |
| `startDate` | string | 否 | 格式 `yyyy-MM-dd` |
| `endDate` | string | 否 | 格式 `yyyy-MM-dd` |
### 9.3 统计口径
已就业人数统计有效且已录用的求职记录:
```text
job_apply.del_flag = '0'
job_apply.hire = '0'
app_user.del_flag = '0'
app_user.is_company_user = '1'
app_user.status = '0'
```
就业区域根据求职者 `app_user.area` 进行统计。
录用来源映射:
| `hire_source` | 返回名称 |
|---|---|
| `0` | 本系统 |
| `1` | 招聘会 |
| 其他值 | 其他 |
新入职确认人数来自 `employee_confirm` 表的有效确认记录。
### 9.4 返回结构
```json
{
"areaCode": "659001000000",
"areaName": "石河子市",
"totalHired": 86,
"byHireSource": {
"本系统": 52,
"招聘会": 26,
"其他": 8
},
"newEmployeeConfirmed": 31
}
```
### 9.5 字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| `areaCode` | string | 实际统计区域编码 |
| `areaName` | string | 实际统计区域名称 |
| `totalHired` | number | 有效已录用人数 |
| `byHireSource` | object | 录用来源名称到人数的映射 |
| `newEmployeeConfirmed` | number | 新入职确认人数 |
## 10. 接口汇总
| 统计模块 | 请求地址 | 主要用途 |
|---|---|---|
| 业务统计 | `GET /cms/statics/business` | 按月统计岗位来源和新增注册人数 |
| 招聘会统计 | `GET /cms/outdoor-fair/statistics` | 按日/周/月/季度/年度统计招聘会 |
| 求职统计 | `GET /cms/statics/jobSeeker` | 统计求职者年龄、工作经验、专业 |
| 热门岗位统计 | `GET /cms/statics/hotJob` | 统计 `job_hot` 字典配置的热门岗位数量 |
| 用人单位统计 | `GET /cms/statics/company` | 统计单位规模/性质及其发布岗位数量 |
| 区划企业分析 | `GET /cms/areaAnalysis/company` | 按区域统计企业总数、行业、规模、性质 |
| 区划岗位分析 | `GET /cms/areaAnalysis/job` | 按区域统计岗位、招聘人数、薪资、学历等 |
| 区划就业分析 | `GET /cms/areaAnalysis/employment` | 按区域统计已录用和新入职确认数据 |