日期: 2026-06-04
个人基本信息模块(personal)是招聘管理系统中的核心基础模块,负责管理求职者的个人信息和简历信息。该模块采用 JeecgBoot 的前后端分离架构,前端基于 Vue3 + Ant Design Vue,后端基于 Spring Boot + MyBatis-Plus。
| 文件 | 用途 |
|---|---|
PersonalInfoList.vue |
个人信息列表页面,提供查询、新增、编辑、删除、导入导出等功能 |
PersonalInfo.api.ts |
个人信息 API 封装 |
PersonalInfo.data.ts |
列表页表格列配置与搜索字段定义 |
ResumeInfo.api.ts |
简历信息 API 封装 |
ResumeInfo.data.ts |
简历表格列配置与搜索字段定义 |
components/PersonalInfoForm.vue |
个人信息新增/编辑/详情表单组件 |
components/PersonalInfoModal.vue |
个人信息弹窗组件,包裹 PersonalInfoForm |
components/ResumeInfoForm.vue |
简历信息表单组件 |
components/ResumeInfoModal.vue |
简历信息弹窗组件,包裹 ResumeInfoForm |
components/ResumeListModal.vue |
简历列表弹窗组件,查看个人信息关联的简历 |
| 层次 | 文件 |
|---|---|
| Controller | PersonalInfoController.java, ResumeInfoController.java |
| Entity | PersonalInfo.java, ResumeInfo.java, 及 8 个子表实体 |
| Service | IPersonalInfoService.java, IResumeInfoService.java 及 8 个子表 Service |
| Service Impl | 对应 10 个 Service 的实现类 |
| Mapper | 11 个 Mapper 接口 |
| Mapper XML | 10 个 MyBatis XML 映射文件 |
| VO/DTO | ResumeInfoPage.java, ResumeInfoDTO.java |
| 日期 | 内容 | 涉及文件 | 说明 |
|---|---|---|---|
| 2026-06-04 | 个人基本信息模块初始构建 | 前端 10 个文件 + 后端 30+ 文件 | 完成个人信息与简历管理的基础 CRUD 功能 |
问题描述: 在个人信息列表页,先点击"编辑"后关闭弹窗,再点击"详情"时,表单字段和图片上传组件未处于禁用/只读状态。
复现条件: 页面刷新后先点编辑再点详情才会出现;页面刷新后直接点详情则正常禁用。
原因分析: Ant Design Vue 的 <a-modal> 默认 destroyOnClose=false,弹窗关闭时内部组件(PersonalInfoForm)仍然挂载在
DOM 中。
formDisabled=false 的状态挂载disableSubmit 被设为 true,但由于组件实例未重新创建,props 的响应式更新未能正确触发
JFormContainer 的 <fieldset disabled> 状态变更第一次修复(已废弃): 在 <j-modal> 上添加 destroyOnClose 属性,每次关闭弹窗时销毁 PersonalInfoForm 组件。
问题: destroyOnClose 导致组件销毁后 registerForm.value 为 null,打开弹窗后 Vue 重新渲染组件时 ref 还未赋值,
handleOk() 调用 registerForm.value.submitForm() 报错 Cannot read properties of null (reading 'submitForm')。
第二次修复(已废弃): 使用 v-if="visible" 手动控制组件创建/销毁。
问题: 导致多个控制台错误(日期转换报错、异步组件加载报错等)。
最终修复方案: 使用 :key 方式强制组件重建。
formKey ref 和 nextFormKey() 方法<PersonalInfoForm> 上绑定 :key="formKey"nextFormKey() 递增 key,触发 Vue 重建组件实例v-if 控制),ref 在重建完成后自然可用涉及文件:
jeecgboot-vue3/src/views/recruitment/personal/components/PersonalInfoModal.vue — 改用 :key 替代 v-if 控制组件重建问题描述: 打开编辑弹窗时控制台出现 5 类错误:
FormItem can only collect one field item — 年龄搜索字段两个 AInputNumber 在同一 a-form-item 中date.locale is not a function — 日期字符串未转为 dayjs 对象Cannot read properties of null (reading 'type') — 日期错误的级联报错Cannot read properties of null (reading 'submitForm') — registerForm.value 为空Cannot read properties of undefined (reading '__asyncLoader') — 组件异步加载异常原因分析与修复方案:
| 错误 | 原因 | 修复 |
|---|---|---|
| FormItem 警告 | 年龄范围搜索字段中两个 AInputNumber 被同一个 a-form-item 收集 |
用 <a-form-item-rest> 包裹第二个 AInputNumber,告知 Form 不收集该字段 |
date.locale is not a function |
API 返回的日期字符串 "2000-01-15" 直接赋给 a-date-picker 的 v-model:value,但 a-date-picker 期望 dayjs 对象 |
在 PersonalInfoForm.edit() 方法中将 birthDate 和 graduationDate 字符串转为 dayjs() 对象 |
| 级联错误 | 日期转换错误导致 a-date-picker 内部操作失败 |
修复日期转换后自动解决 |
submitForm 报错 |
v-if="visible" 导致组件未挂载时 ref 为 null |
改用 :key 方式重建组件(同上修复1) |
__asyncLoader 报错 |
组件重建时序问题导致异步组件加载异常 | 改用 :key 重建后解决 |
涉及文件:
jeecgboot-vue3/src/views/recruitment/personal/components/PersonalInfoForm.vue — edit 方法增加日期字符串转 dayjs
对象逻辑;引入 dayjs 依赖jeecgboot-vue3/src/views/recruitment/personal/components/PersonalInfoModal.vue — 改用 :key 替代 v-ifjeecgboot-vue3/src/views/recruitment/personal/PersonalInfoList.vue — 年龄搜索字段用 <a-form-item-rest> 包裹第二个
AInputNumber