# 就业状态自动感知模块 - 开发设计文档 > 依据:《需求规格说明书》第3.9节 > 设计日期:2026-06-09 > 设计模式:视图分页查询 + 轻量本地标签表 --- ## 一、菜单层级 ``` 就业状态自动感知 (顶级菜单, sort_no: 2.00, icon: eye-outlined) ├── 企业就业状态感知 (子菜单, sort_no: 1.00) └── 个人就业状态感知 (子菜单, sort_no: 2.00) ``` --- ## 二、子模块1:企业就业状态感知 ### 2.1 功能说明 企业就业状态自动感知,监测企业在岗员工总数、用工工种分布、用工稳定性、薪酬待遇等数据。通过对这些数据的分析,准确掌握就业失业状况及其变化趋势。 ### 2.2 查询字段 所属区县,所属行业,企业名称,企业状态,自定义标签 ### 2.3 列表字段 企业名称,所属区县,企业规模,企业状态,所属行业,企业已发布岗位总数,当前在招岗位数量,备案在岗总人数,平均薪酬,自定义标签,最后通知时间 ### 2.4 支持功能 查看,发送消息,修改标签 ### 2.5 数据库设计 #### 表:企业就业状态本地信息表(enterprise_status_local) ```sql CREATE TABLE ENTERPRISE_STATUS_LOCAL ( ID VARCHAR(36) NOT NULL, ENTERPRISE_ID VARCHAR(36) NOT NULL COMMENT '企业ID(关联ENTERPRISE_INFO.ID)', CUSTOM_TAGS VARCHAR(500) COMMENT '自定义标签', LAST_NOTICE_TIME DATETIME COMMENT '最后通知时间', CREATE_BY VARCHAR(50), CREATE_TIME DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UPDATE_BY VARCHAR(50), UPDATE_TIME DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, SYS_ORG_CODE VARCHAR(50), PRIMARY KEY (ID) ); COMMENT ON TABLE ENTERPRISE_STATUS_LOCAL IS '企业就业状态本地信息表'; CREATE UNIQUE INDEX IDX_ESL_ENTERPRISE ON ENTERPRISE_STATUS_LOCAL(ENTERPRISE_ID); ``` #### 视图:v_enterprise_employment_status 从 ENTERPRISE_INFO + POST_INFO + ENTERPRISE_STATUS_LOCAL 聚合: ```sql CREATE OR REPLACE VIEW V_ENTERPRISE_EMPLOYMENT_STATUS AS SELECT ei.ID, ei.UNIFIED_CREDIT_CODE, ei.COMPANY_NAME, ei.REG_ADDR_DISTRICT AS DISTRICT, ei.INDUSTRY, ei.STAFF_SIZE AS ENTERPRISE_SCALE, ei.BUSINESS_STATUS AS ENTERPRISE_STATUS, (SELECT COUNT(*) FROM POST_INFO pi WHERE pi.ENTERPRISE_ID = ei.ID) AS TOTAL_POST_COUNT, (SELECT COUNT(*) FROM POST_INFO pi WHERE pi.ENTERPRISE_ID = ei.ID AND (pi.POST_VALID_DATE IS NULL OR pi.POST_VALID_DATE >= SYSDATE)) AS ACTIVE_POST_COUNT, (SELECT COUNT(*) FROM POST_INFO pi WHERE pi.ENTERPRISE_ID = ei.ID AND pi.POST_VALID_DATE IS NOT NULL AND pi.POST_VALID_DATE < SYSDATE) AS EXPIRED_POST_COUNT, NULL AS REGISTERED_EMPLOYEE_COUNT, (SELECT AVG((pi2.SALARY_MIN + pi2.SALARY_MAX) / 2) FROM POST_INFO pi2 WHERE pi2.ENTERPRISE_ID = ei.ID AND (pi2.POST_VALID_DATE IS NULL OR pi2.POST_VALID_DATE >= SYSDATE) AND pi2.SALARY_MIN IS NOT NULL AND pi2.SALARY_MAX IS NOT NULL) AS AVERAGE_SALARY, esl.CUSTOM_TAGS, esl.LAST_NOTICE_TIME FROM ENTERPRISE_INFO ei LEFT JOIN ENTERPRISE_STATUS_LOCAL esl ON ei.ID = esl.ENTERPRISE_ID; ``` ### 2.6 文件清单 #### 后端(jeecg-module-zjrs/org/jeecg/modules/zjrs/enterprisestatus/) | 文件 | 说明 | |------|------| | entity/EnterpriseStatusLocal.java | 本地信息实体 | | entity/EnterpriseStatusPageVo.java | 列表页VO(视图字段) | | mapper/EnterpriseStatusLocalMapper.java | Mapper(含queryPageList) | | mapper/xml/EnterpriseStatusLocalMapper.xml | 视图查询SQL | | service/IEnterpriseStatusService.java | 服务接口 | | service/impl/EnterpriseStatusServiceImpl.java | 服务实现(含queryPageList) | | controller/EnterpriseStatusController.java | REST控制器(列表+标签保存) | #### 前端(jeecgboot-vue3/src/views/enterprisestatus/) | 文件 | 说明 | |------|------| | EnterpriseStatusList.vue | 列表页面(含查询表单) | | EnterpriseStatus.data.ts | 表格列+搜索配置 | | EnterpriseStatus.api.ts | API接口 | ### 2.7 业务逻辑 1. 企业就业状态数据从省一体化平台回流,通过视图实时聚合 2. 管理员可以给企业打自定义标签(存enterprise_status_local) 3. 发送消息功能:基于企业信息发送通知(待实现消息推送) --- ## 三、子模块2:个人就业状态感知 ### 3.1 功能说明 个人就业状态自动感知,监控求职人员就业情况。 ### 3.2 查询字段 户口所属区域,姓名,学历,性别,年龄,求职状态,就业状态 ### 3.3 列表字段 证件号码,姓名,户口所属区县,性别,学历,年龄,求职状态,就业状态,就业登记累计次数,失业登记累计次数,社保情况,自定义标签,最后通知时间 ### 3.4 支持功能 查看,发送消息,修改标签 ### 3.5 数据库设计 #### 表:个人就业状态本地信息表(personal_status_local) ```sql CREATE TABLE PERSONAL_STATUS_LOCAL ( ID VARCHAR(36) NOT NULL, PERSONAL_ID VARCHAR(36) NOT NULL COMMENT '个人ID(关联PERSONAL_INFO.ID)', CUSTOM_TAGS VARCHAR(500) COMMENT '自定义标签', LAST_NOTICE_TIME DATETIME COMMENT '最后通知时间', CREATE_BY VARCHAR(50), CREATE_TIME DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UPDATE_BY VARCHAR(50), UPDATE_TIME DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, SYS_ORG_CODE VARCHAR(50), PRIMARY KEY (ID) ); COMMENT ON TABLE PERSONAL_STATUS_LOCAL IS '个人就业状态本地信息表'; CREATE UNIQUE INDEX IDX_PSL_PERSONAL ON PERSONAL_STATUS_LOCAL(PERSONAL_ID); ``` #### 视图:v_personal_employment_status 从 PERSONAL_INFO + EMPLOYMENT_RECORD + UNEMPLOYMENT_RECORD 聚合: ```sql CREATE OR REPLACE VIEW V_PERSONAL_EMPLOYMENT_STATUS AS SELECT pi.ID, pi.ID_NUMBER, pi.FULL_NAME, pi.HOUSEHOLD_LOCATION AS HOUSEHOLD_DISTRICT, pi.GENDER, pi.EDUCATION, FLOOR(MONTHS_BETWEEN(SYSDATE, pi.BIRTH_DATE) / 12) AS AGE, pi.JOB_SEARCH_STATUS, CASE WHEN er.PERSONAL_ID IS NOT NULL AND er.EMPLOY_COUNT > 0 THEN '就业中' WHEN ur.PERSONAL_ID IS NOT NULL AND ur.UNEMPLOY_COUNT > 0 THEN '失业中' ELSE '未就业' END AS EMPLOYMENT_STATUS, NVL(er.EMPLOY_COUNT, 0) AS EMPLOY_REG_COUNT, NVL(ur.UNEMPLOY_COUNT, 0) AS UNEMPLOY_REG_COUNT, NULL AS SOCIAL_INSURANCE_STATUS, psl.CUSTOM_TAGS, psl.LAST_NOTICE_TIME FROM PERSONAL_INFO pi LEFT JOIN PERSONAL_STATUS_LOCAL psl ON pi.ID = psl.PERSONAL_ID LEFT JOIN (SELECT PERSONAL_ID, COUNT(*) AS EMPLOY_COUNT FROM EMPLOYMENT_RECORD GROUP BY PERSONAL_ID) er ON pi.ID = er.PERSONAL_ID LEFT JOIN (SELECT PERSONAL_ID, COUNT(*) AS UNEMPLOY_COUNT FROM UNEMPLOYMENT_RECORD GROUP BY PERSONAL_ID) ur ON pi.ID = ur.PERSONAL_ID; ``` ### 3.6 文件清单 #### 后端(jeecg-module-zjrs/org/jeecg/modules/zjrs/personalstatus/) | 文件 | 说明 | |------|------| | entity/PersonalStatusLocal.java | 本地信息实体 | | entity/PersonalStatusPageVo.java | 列表页VO(视图字段) | | mapper/PersonalStatusLocalMapper.java | Mapper(含queryPageList) | | mapper/xml/PersonalStatusLocalMapper.xml | 视图查询SQL | | service/IPersonalStatusService.java | 服务接口 | | service/impl/PersonalStatusServiceImpl.java | 服务实现(含queryPageList) | | controller/PersonalStatusController.java | REST控制器(列表+标签保存) | #### 前端(jeecgboot-vue3/src/views/personalstatus/) | 文件 | 说明 | |------|------| | PersonalStatusList.vue | 列表页面(含查询表单) | | PersonalStatus.data.ts | 表格列+搜索配置 | | PersonalStatus.api.ts | API接口 | ### 3.7 业务逻辑 1. 就业状态判断规则:有有效就业登记→就业中,有有效失业登记→失业中,否则→未就业 2. 管理员可以给个人打自定义标签 3. 就业/失业登记累计次数根据省平台回流数据统计 --- ## 九、2026-06-10 修复与优化记录 ### 编译修复 - `EnterpriseStatusController.java` / `PersonalStatusController.java` — `javax.servlet` → `jakarta.servlet` - `EnterpriseStatusServiceImpl.java` / `PersonalStatusServiceImpl.java` — `javax.annotation.Resource` → `jakarta.annotation.Resource` - 移除不存在的 `org.jeecg.common.util.ParamUtils` 引用,改为手动 `req.getParameter()` 提取参数 - `IEnterpriseStatusService.java` / `IPersonalStatusService.java` — 补充 `queryPageList` 方法声明 ### 后端新增 - `EnterpriseStatusController.java` / `PersonalStatusController.java` — 新增 `/exportXls` 导出端点,支持 `selections` 勾选过滤 - `EnterpriseStatusPageVo.java` — 新增 `registeredEmployeeCount`(备案在岗总人数)、`averageSalary`(平均薪酬)、`@Excel` 注解 - `PersonalStatusPageVo.java` — 新增 `socialInsuranceStatus`(社保情况)、`householdAreaName`(户口区县名称)、`@Excel` 注解 - `EnterpriseStatusLocalMapper.xml` — 新增 `customTags` 查询条件 - `PersonalStatusLocalMapper.xml` — 新增 `age` 查询条件 ### 前端修复 **企业就业状态感知:** - 企业状态搜索框 → `` 下拉(BusinessStatus 字典) - 表格列翻译:`enterpriseStatus`(BusinessStatus)、`enterpriseScale`(enterprise_scale)、`district`(XZQH) - 新增导出按钮 + `exportConfig` - 新增 `EnterpriseStatusModal.vue` + `EnterpriseStatusDetail.vue` 详情弹窗(j-modal 模式,与重点关注人员一致) - 列标题修正:`已发布岗位总数` → `企业已发布岗位总数` **个人就业状态感知:** - 性别/学历/求职状态/就业状态搜索框 → `` 下拉(Gender/Education/JobSeekerStatus/employment_status 字典) - 表格列翻译:gender/education/jobSearchStatus/employmentStatus - 户口所属区县列 → `householdAreaName` 去"广东省湛江市"前缀显示区名 - 新增导出按钮 + `exportConfig` - 新增 `PersonalStatusModal.vue` + `PersonalStatusDetail.vue` 详情弹窗 ### DM8 数据库 - 建表:`ENTERPRISE_STATUS_LOCAL`、`PERSONAL_STATUS_LOCAL` - 建视图:`V_ENTERPRISE_EMPLOYMENT_STATUS`、`V_PERSONAL_EMPLOYMENT_STATUS` - 建字典:`employment_status`(就业状态)、`enterprise_scale`(企业规模) - 菜单权限:`就业状态自动感知`(178060400000000) → `企业就业状态感知`(178060400000001) → `个人就业状态感知`(178060400000002),含 admin 授权 - PERSONAL_INFO:20人,全部使用数字编码,覆盖湛江8区县 - ENTERPRISE_INFO:10家,含对应标签 - 旧人员数据(200-209)更新为湛江区县 + 多样化性别/学历/求职状态 ## 十、2026-06-11 修复与优化记录 ### 搜索表单优化 **企业就业状态感知:** - 所属区县 → 树形下拉(XZQH 懒加载,程序化定位湛江市区县) - 所属行业 → `` 下拉(EconomicIndustry 字典,value 使用 label 文本匹配 DB) - 企业状态 → `` 下拉(BusinessStatus 字典,与企业基本信息模块经营状态保持一致) - 表格列 `enterpriseStatus` 去掉 `|| text` 回退(字典未匹配时显示空白) - 新增"统一社会信用代码"搜索字段(模糊匹配) - 行业搜索从 `=` 改为 `LIKE` 模糊匹配 **个人就业状态感知:** - 户口所属区县 → 树形下拉(XZQH 懒加载,程序化定位湛江市区县) - 年龄 → 改为范围搜索(`ageBegin ~ ageEnd`,后端同步改造) - 就业状态 → `` 下拉(employment_status 字典,value 使用 label 文本匹配) - `householdDistrict` 搜索从 `=` 改为 `LIKE` 模糊匹配 ### 自定义标签编辑 - `EnterpriseStatusList.vue` / `PersonalStatusList.vue` — "修改标签"按钮弹出模态框,使用 `` 编辑逗号分隔标签 - 通过 `saveTag`/`getTag` API 读写 `enterprise_status_local`/`personal_status_local` 表的 `custom_tags` 字段 ### 发送消息功能 **共用消息表:** `notification_record`,支持多模块复用 | 字段 | 说明 | |------|------| | MODULE_TYPE | 模块类型(enterprise_status/personal_status/profile_change 等) | | TARGET_ID | 目标ID(企业ID或个人ID) | | TARGET_NAME | 目标名称(冗余展示) | | SUBJECT | 消息主题 | | CONTENT | 消息内容 | | SENDER | 推送人(自动绑定当前登录用户) | | SEND_TIME | 推送时间(自动记录) | **后端新增:** - `notification/entity/NotificationRecord.java` — 消息记录实体 - `notification/mapper/NotificationRecordMapper.java` + XML - `notification/service/INotificationRecordService.java` + Impl - `notification/controller/NotificationController.java` — 统一接口: - `POST /notification/send` — 发送消息(写记录 + 更新 local 表 last_notice_time) - `GET /notification/list` — 分页查询消息记录 - `GET /notification/myList` — 查询当前用户发送的消息(支持关键字/模块/日期筛选) **前端新增:** - `notification/SentMessagesList.vue` — 已发送消息列表页(搜索:关键字、来源模块、推送时间范围;详情弹窗) - `notification/SentMessages.data.ts` — 列定义 - `notification/SentMessages.api.ts` — API **企业/个人就业状态感知:** - "发送消息"按钮弹出表单弹窗(接收对象、主题、内容、推送人、推送时间) - 调用 `/notification/send`,自动更新 `last_notice_time` **菜单:** - 新增"消息中心"顶级菜单(sort_no: 3.00, icon: message-outlined) - 下挂"已发送消息"子菜单(sort_no: 1.00, icon: send-outlined) **字典:** - `notification_module`(消息通知来源模块):企业就业状态感知、个人就业状态感知、画像变动管理、重点关注人员管理、就业援助、初步符合人员 **数据库表:** - DM8:`notification_record`(含索引 idx_notice_target、idx_notice_time) - Flyway MySQL:`V20260611_1__create_notification_record.sql`、`V20260611_2__menu_insert_SentMessages.sql` ### 架构优化:消息与接收人分离 将原有 `notification_record` 重构为消息主表 + 接收人关联表: ``` notification_record notification_target ┌──────────────┐ ┌────────────────────┐ │ id │◄───1:N────│ notification_id │ │ module_type │ │ target_type │ (personal/enterprise) │ subject │ │ target_id │ │ content │ └────────────────────┘ │ sender │ │ send_time │ └──────────────┘ ``` - 批量发送:1 条 record + N 条 target,subject/content 不重复 - `target_name` 不存储,查询时从 `PERSONAL_INFO`/`ENTERPRISE_INFO` 批量关联获取 `resolveTargetNames()` - 统一 `/notification/send` 端点,接收 `targets: [{targetType, targetId}]` 数组,单条传 1 个元素,批量传多个 - `NotificationTarget` 实体(mapper: `NotificationTargetMapper`) - `NotificationTarget.targetName` 为 `@TableField(exist = false)` 瞬态字段 ### 画像变动管理 同步实现 - `ProfileChangeList.vue` — "修改标签"和"发送消息"功能实现,与个人就业状态感知共用 `personal_status_local` 表 - `ProfileChange.api.ts` — `saveTag` 修复为 `data` 请求体 ### 模块类型字典 - `DICTIONARY` 新增 `notification_module`(消息通知来源模块) - `DICTIONARY_ITEM` 写入 6 项:enterprise_status / personal_status / profile_change / focus_personnel / employment_assistance / preliminary_eligible - 前端 `SentMessagesList.vue` 通过 `useDict('notification_module')` 加载,`moduleTypeMap` 动态映射 code→label ### 搜索条件优化补充 - 个人就业状态感知 `householdDistrict` 改用 XZQH 树形下拉(程序化定位湛江市区县) - `PersonalStatusLocalMapper.xml` — `household_district` 从 `=` 改为 `LIKE` - `PersonalStatusController.java` — 年龄从单值 `age` 改为范围 `ageBegin`/`ageEnd` ### 批量消息推送(信息智能匹配推送) - `FocusPersonnelList.vue` / `InternshipPersonnelList.vue` — "推送消息"按钮替换为模态框(显示已选N条,富文本内容,自动推送人/时间) - 勾选多条 → 从 `getDataSource()` 提取 `personalId` → 调用 `/notification/send`,`targets` 数组批量发送 - `FocusPersonnel.data.ts` / `InternshipPersonnel.data.ts` — 新增隐藏列 `personalId`(`ifShow: false`)确保数据可用 - `DICTIONARY_ITEM` 补充 `internship_personnel` 字典项 ### 表结构优化 - `notification_record` 新增 `SENDER_ID VARCHAR(36)`(关联 `sys_user.id`),`sender` 存姓名冗余展示 - `create_by` 为 JeecgBoot 标准字段(存 `sys_user.username`) --- ## 2026-06-12 导出日期格式修复 ### 问题 导出Excel时日期格式异常,因 `ExportParams` 缺少 `ExcelType.XSSF`。 ### 修复文件 | 文件 | 修改 | |------|------| | `PersonalStatusController.java` | `ExportParams` 补 `ExcelType.XSSF` |