diff --git a/doc/other/ScreenShot_2026-02-05_154534_027.png b/doc/other/ScreenShot_2026-02-05_154534_027.png
new file mode 100644
index 0000000..e0857c7
Binary files /dev/null and b/doc/other/ScreenShot_2026-02-05_154534_027.png differ
diff --git a/doc/plans/2025-02-05-ccdi_staff_recruitment.md b/doc/plans/2025-02-05-ccdi_staff_recruitment.md
new file mode 100644
index 0000000..87f09e0
--- /dev/null
+++ b/doc/plans/2025-02-05-ccdi_staff_recruitment.md
@@ -0,0 +1,347 @@
+# 员工招聘信息管理功能设计文档
+
+**文档版本:** 1.0
+**创建日期:** 2025-02-05
+**模块名称:** ccdi-staff-recruitment
+**作者:** Claude
+
+---
+
+## 1. 概述
+
+### 1.1 功能简介
+员工招聘信息管理模块提供招聘信息的记录、查询、导入导出等基础维护功能,支持单条和批量操作。
+
+### 1.2 业务场景
+- 简单的招聘信息记录,作为数据存档使用
+- 支持招聘信息的增删改查操作
+- 支持Excel批量导入和导出
+
+### 1.3 技术选型
+- **后端框架:** Spring Boot 3.5.8 + MyBatis Plus 3.5.10
+- **数据库:** MySQL 8.2.0
+- **前端框架:** Vue 2.6.12 + Element UI 2.15.14
+- **数据校验:** javax.validation + 自定义校验注解
+
+---
+
+## 2. 数据库设计
+
+### 2.1 表结构
+
+**表名:** `ccdi_staff_recruitment`
+
+```sql
+CREATE TABLE `ccdi_staff_recruitment` (
+ `recruit_id` varchar(32) NOT NULL COMMENT '招聘项目编号',
+ `recruit_name` varchar(100) NOT NULL COMMENT '招聘项目名称',
+ `pos_name` varchar(100) NOT NULL COMMENT '职位名称',
+ `pos_category` varchar(50) NOT NULL COMMENT '职位类别',
+ `pos_desc` text NOT NULL COMMENT '职位描述',
+ `cand_name` varchar(20) NOT NULL COMMENT '应聘人员姓名',
+ `cand_edu` varchar(20) NOT NULL COMMENT '应聘人员学历',
+ `cand_id` varchar(18) NOT NULL COMMENT '应聘人员证件号码',
+ `cand_school` varchar(50) NOT NULL COMMENT '应聘人员毕业院校',
+ `cand_major` varchar(30) NOT NULL COMMENT '应聘人员专业',
+ `cand_grad` varchar(6) NOT NULL COMMENT '应聘人员毕业年月',
+ `admit_status` varchar(10) NOT NULL COMMENT '录用情况:录用、未录用、放弃',
+ `interviewer_name1` varchar(20) DEFAULT NULL COMMENT '面试官1姓名',
+ `interviewer_id1` varchar(10) DEFAULT NULL COMMENT '面试官1工号',
+ `interviewer_name2` varchar(20) DEFAULT NULL COMMENT '面试官2姓名',
+ `interviewer_id2` varchar(10) DEFAULT NULL COMMENT '面试官2工号',
+ `created_by` varchar(20) NOT NULL COMMENT '记录创建人',
+ `updated_by` varchar(20) DEFAULT NULL COMMENT '记录更新人',
+ `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`recruit_id`),
+ KEY `idx_cand_id` (`cand_id`),
+ KEY `idx_admit_status` (`admit_status`),
+ KEY `idx_interviewer_id1` (`interviewer_id1`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工招聘信息表';
+```
+
+### 2.2 索引设计
+- **主键索引:** `recruit_id`
+- **业务索引:** `cand_id`, `admit_status`, `interviewer_id1`
+
+### 2.3 枚举值设计
+
+**录用状态 (admit_status):**
+| 枚举值 | 说明 |
+|--------|------|
+| 录用 | 已录用该候选人 |
+| 未录用 | 未录用该候选人 |
+| 放弃 | 候选人放弃 |
+
+---
+
+## 3. 后端设计
+
+### 3.1 模块结构
+
+```
+ruoyi-ccdi/
+├── domain/
+│ ├── CcdiStaffRecruitment.java # 实体类
+│ ├── dto/
+│ │ ├── CcdiStaffRecruitmentQueryDTO.java # 查询DTO
+│ │ ├── CcdiStaffRecruitmentAddDTO.java # 新增DTO
+│ │ └── CcdiStaffRecruitmentEditDTO.java # 修改DTO
+│ ├── vo/
+│ │ └── CcdiStaffRecruitmentVO.java # 返回VO
+│ └── excel/
+│ └── CcdiStaffRecruitmentExcel.java # Excel导入导出类
+├── mapper/
+│ ├── CcdiStaffRecruitmentMapper.java # MyBatis Mapper接口
+│ └── xml/
+│ └── CcdiStaffRecruitmentMapper.xml # MyBatis XML映射
+├── service/
+│ ├── ICcdiStaffRecruitmentService.java # 服务接口
+│ └── impl/
+│ └── CcdiStaffRecruitmentServiceImpl.java # 服务实现
+└── controller/
+ └── CcdiStaffRecruitmentController.java # 控制器
+```
+
+### 3.2 API接口设计
+
+**基础路径:** `/ccdi/staffRecruitment`
+
+| 接口功能 | HTTP方法 | 路径 | 权限标识 |
+|---------|---------|------|---------|
+| 分页查询 | GET | `/list` | ccdi:staffRecruitment:list |
+| 详情查询 | GET | `/{recruitId}` | ccdi:staffRecruitment:query |
+| 新增 | POST | `/` | ccdi:staffRecruitment:add |
+| 修改 | PUT | `/` | ccdi:staffRecruitment:edit |
+| 删除 | DELETE | `/{recruitIds}` | ccdi:staffRecruitment:remove |
+| 导入模板下载 | GET | `/importTemplate` | ccdi:staffRecruitment:import |
+| 批量导入 | POST | `/importData` | ccdi:staffRecruitment:import |
+| 导出 | POST | `/export` | ccdi:staffRecruitment:export |
+
+### 3.3 查询参数设计
+
+**CcdiStaffRecruitmentQueryDTO:**
+```java
+// 查询条件
+private String recruitName; // 招聘项目名称(模糊查询)
+private String posName; // 职位名称(模糊查询)
+private String candName; // 候选人姓名(模糊查询)
+private String candId; // 证件号码(精确查询)
+private String admitStatus; // 录用状态(精确查询)
+private String interviewerName; // 面试官姓名(模糊查询,查询面试官1或2)
+private String interviewerId; // 面试官工号(精确查询,查询面试官1或2)
+
+// 分页参数
+private Integer pageNum = 1;
+private Integer pageSize = 10;
+```
+
+### 3.4 数据校验规则
+
+| 字段 | 校验规则 | 错误提示 |
+|-----|---------|---------|
+| recruitName | @NotBlank, @Size(max=100) | 招聘项目名称不能为空/长度不能超过100 |
+| posName | @NotBlank, @Size(max=100) | 职位名称不能为空/长度不能超过100 |
+| candName | @NotBlank, @Size(max=20) | 应聘人员姓名不能为空/长度不能超过20 |
+| candId | @NotBlank, @Pattern(身份证正则) | 证件号码不能为空/格式不正确 |
+| candGrad | @NotBlank, @Pattern(YYYYMM) | 毕业年月不能为空/格式不正确 |
+| admitStatus | @NotBlank, @EnumValid | 录用情况不能为空/状态值不合法 |
+
+### 3.5 批量导入功能设计
+
+**核心优化点:**
+1. **批量查询已存在记录:** 使用 `selectBatchIds` 一次性查询
+2. **批量插入:** 使用 `saveBatch()` 方法
+3. **批量更新:** 使用 `updateBatchById()` 方法
+4. **错误信息:** 只返回错误的数据行,成功数据不展示
+
+**性能提升:**
+- 原方案: ~3000次数据库操作 (导入1000条)
+- 优化后: ~3次数据库操作 (导入1000条)
+- 性能提升: ~1000倍
+
+**导入逻辑:**
+```
+1. 收集所有recruit_id
+2. 批量查询已存在的记录
+3. 遍历Excel数据:
+ - 数据转换和校验
+ - 分类为: 待新增列表、待更新列表
+ - 记录校验失败的数据
+4. 批量插入待新增数据
+5. 批量更新待更新数据
+6. 只返回错误信息
+```
+
+---
+
+## 4. 前端设计
+
+### 4.1 页面结构
+
+```
+ruoyi-ui/src/views/ccdiStaffRecruitment/
+├── index.vue # 列表页面(主页面)
+└── components/
+ ├── RecruitmentForm.vue # 新增/修改表单组件
+ └── ImportDialog.vue # 导入对话框组件
+```
+
+### 4.2 功能列表
+
+**列表页面 (index.vue):**
+- 顶部查询表单
+ - 招聘项目名称(模糊查询)
+ - 职位名称(模糊查询)
+ - 候选人姓名(模糊查询)
+ - 证件号码(精确查询)
+ - 录用状态(下拉选择)
+ - 面试官姓名(模糊查询)
+ - 面试官工号(精确查询)
+- 数据表格
+ - 展示所有字段信息
+ - 支持排序
+- 操作按钮
+ - 新增
+ - 批量导入
+ - 导出
+ - 批量删除
+- 行操作
+ - 修改
+ - 删除
+
+**表单组件 (RecruitmentForm.vue):**
+- 所有必填字段添加 `required: true`
+- 证件号码正则校验
+- 毕业年月格式校验(YYYYMM)
+- 录用状态下拉选择(枚举值)
+
+---
+
+## 5. 异常处理
+
+### 5.1 异常分类
+
+| 异常类型 | HTTP状态码 | 使用场景 |
+|---------|-----------|---------|
+| ServiceException | 500 | 业务逻辑异常 |
+| ValidationException | 400 | 参数校验失败 |
+| DuplicateKeyException | 409 | 主键冲突 |
+| FileNotFoundException | 404 | 文件不存在 |
+
+### 5.2 统一异常处理
+
+使用 `@RestControllerAdvice` 全局异常处理器捕获和处理异常。
+
+---
+
+## 6. 测试策略
+
+### 6.1 单元测试
+
+**测试范围:**
+- 实体类校验注解测试
+- 数据转换工具方法测试
+- 业务逻辑核心方法测试
+
+**关键测试用例:**
+1. 正常数据导入测试
+2. 身份证格式校验测试
+3. 批量插入性能测试
+
+### 6.2 集成测试
+
+**测试流程:**
+1. 登录获取Token
+2. 分页查询测试
+3. 单条新增测试
+4. 单条修改测试
+5. 批量导入测试
+6. 导出测试
+7. 批量删除测试
+
+### 6.3 性能指标
+
+| 测试场景 | 预期性能 |
+|---------|---------|
+| 分页查询(1000条) | < 200ms |
+| 单条新增 | < 100ms |
+| 批量导入(1000条) | < 5s |
+| 批量删除(100条) | < 500ms |
+| 导出(1000条) | < 2s |
+
+---
+
+## 7. 实施步骤
+
+### 第一步:数据库准备
+1. 执行建表SQL
+2. 在菜单表中添加菜单和权限配置
+
+### 第二步:后端开发
+1. 创建枚举类
+2. 创建实体类、DTO、VO、Excel类
+3. 创建Mapper接口和XML
+4. 创建Service接口和实现
+5. 创建Controller
+6. 编写单元测试
+7. Swagger-UI测试
+
+### 第三步:前端开发
+1. 创建API接口定义
+2. 开发表格查询页面
+3. 开发表单组件
+4. 开发导入对话框
+5. 配置路由
+6. 配置菜单
+
+### 第四步:集成测试
+1. 准备测试数据
+2. 执行集成测试
+3. 验证功能
+4. 生成测试报告
+
+### 第五步:文档编写
+1. 生成API文档
+2. 编写使用说明
+
+---
+
+## 8. 附录
+
+### 8.1 Excel导入模板字段顺序
+
+按CSV字段顺序设计:
+1. 招聘项目编号
+2. 招聘项目名称
+3. 职位名称
+4. 职位类别
+5. 职位描述
+6. 应聘人员姓名
+7. 应聘人员学历
+8. 应聘人员证件号码
+9. 应聘人员毕业院校
+10. 应聘人员专业
+11. 应聘人员毕业年月
+12. 录用情况
+13. 面试官1姓名
+14. 面试官1工号
+15. 面试官2姓名
+16. 面试官2工号
+
+### 8.2 MyBatis Plus配置
+
+确保项目中已配置MyBatis Plus分页插件:
+
+```java
+@Bean
+public MybatisPlusInterceptor mybatisPlusInterceptor() {
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+ return interceptor;
+}
+```
+
+---
+
+**文档结束**
diff --git a/doc/plans/2025-02-05-employee-import-result-dialog-optimization.md b/doc/plans/2025-02-05-employee-import-result-dialog-optimization.md
new file mode 100644
index 0000000..b8e3064
--- /dev/null
+++ b/doc/plans/2025-02-05-employee-import-result-dialog-optimization.md
@@ -0,0 +1,395 @@
+# 员工信息导入结果弹窗自适应优化设计
+
+**日期**: 2025-02-05
+**模块**: 员工信息管理 (ccdiEmployee)
+**问题**: 导入结果弹窗在失败数据较多时,内容过长未自适应页面大小
+
+---
+
+## 1. 问题分析
+
+### 1.1 问题描述
+
+当前员工信息维护页面中的导入结果弹窗使用 Element UI 的 `$alert` 组件展示导入结果。当导入失败记录较多(如50+条)时,弹窗会出现以下问题:
+- 弹窗可能超出视口高度
+- 需要滚动整个页面才能看到确定按钮
+- 用户体验不佳
+
+### 1.2 现状分析
+
+**前端实现** (index.vue:500-507):
+```javascript
+handleFileSuccess(response, file, fileList) {
+ this.upload.isUploading = false;
+ this.upload.open = false;
+ this.getList();
+ this.$alert(response.msg, "导入结果", {
+ dangerouslyUseHTMLString: true,
+ customClass: 'import-result-dialog'
+ });
+}
+```
+
+**后端返回格式** (CcdiEmployeeServiceImpl.java:276-296):
+```java
+failureMsg.append("
").append(failureNum).append("、")
+ .append(excel.getName()).append(" 导入失败:").append(e.getMessage());
+// ...
+failureMsg.insert(0, "很抱歉,导入完成!成功 " + successNum + " 条,失败 " + failureNum + " 条,错误如下:");
+```
+
+返回HTML格式示例:
+```html
+很抱歉,导入完成!成功 5 条,失败 10 条,错误如下:
1、张三 导入失败:姓名不能为空
2、李四 导入失败:柜员号不能为空
...
+```
+
+**现有样式** (index.vue:638-662):
+虽然已经设置了 `max-height: 60vh` 和 `overflow-y: auto`,但Element UI MessageBox的布局限制导致效果不理想。
+
+---
+
+## 2. 设计方案
+
+### 2.1 设计目标
+
+1. ✅ 弹窗最大高度不超过视口的70%
+2. ✅ 内容区域独立滚动,标题和按钮固定
+3. ✅ 适配不同屏幕尺寸(包括小屏幕)
+4. ✅ 保持良好的视觉层次和可读性
+
+### 2.2 技术方案
+
+**核心策略**:
+- 使用Flexbox布局确保弹窗结构稳定
+- 优化 `.import-result-dialog` 的CSS样式
+- 调整 MessageBox 内部元素布局权重
+- 添加响应式断点处理小屏幕
+
+---
+
+## 3. 详细设计
+
+### 3.1 弹窗容器优化
+
+```css
+.import-result-dialog.el-message-box {
+ max-height: 70vh !important;
+ max-width: 700px !important;
+ width: 700px !important;
+ display: flex !important;
+ flex-direction: column !important;
+ position: fixed !important;
+ top: 50% !important;
+ left: 50% !important;
+ transform: translate(-50%, -50%) !important;
+}
+```
+
+**设计说明**:
+- `max-height: 70vh`: 比原60vh增加10vh,提供更多展示空间
+- `max-width: 700px`: 增加宽度以提升长错误信息的可读性
+- Flexbox布局:确保三部分(header/content/btns)结构稳定
+- 固定定位+居中:防止弹窗位置偏移
+
+### 3.2 内容区域滚动优化
+
+```css
+.import-result-dialog .el-message-box__content {
+ max-height: calc(70vh - 120px) !important;
+ overflow-y: auto !important;
+ overflow-x: hidden !important;
+ padding: 15px 20px !important;
+ flex-shrink: 1 !important;
+ scrollbar-width: thin;
+ scrollbar-color: #c0c4cc #f5f7fa;
+}
+```
+
+**设计说明**:
+- `max-height: calc(70vh - 120px)`: 减去header和btns高度,确保不超出视口
+- `flex-shrink: 1`: 内容区可收缩,为header和btns留出空间
+- 滚动条优化:thin模式,提升视觉体验
+
+### 3.3 滚动条美化(WebKit浏览器)
+
+```css
+.import-result-dialog .el-message-box__content::-webkit-scrollbar {
+ width: 6px;
+}
+
+.import-result-dialog .el-message-box__content::-webkit-scrollbar-track {
+ background: #f5f7fa;
+ border-radius: 3px;
+}
+
+.import-result-dialog .el-message-box__content::-webkit-scrollbar-thumb {
+ background: #c0c4cc;
+ border-radius: 3px;
+}
+
+.import-result-dialog .el-message-box__content::-webkit-scrollbar-thumb:hover {
+ background: #909399;
+}
+```
+
+**设计说明**:
+- 6px宽度:既清晰又不占用过多空间
+- 圆角设计:与Element UI风格一致
+- hover效果:提供交互反馈
+
+### 3.4 标题和按钮固定
+
+```css
+.import-result-dialog .el-message-box__header {
+ flex-shrink: 0 !important;
+ padding: 15px 20px 10px !important;
+ border-bottom: 1px solid #ebeef5;
+}
+
+.import-result-dialog .el-message-box__btns {
+ flex-shrink: 0 !important;
+ padding: 10px 20px 15px !important;
+ border-top: 1px solid #ebeef5;
+ background: #fff;
+}
+```
+
+**设计说明**:
+- `flex-shrink: 0`: 禁止收缩,始终显示
+- 添加边框:增强三部分视觉分离
+- 背景色:确保按钮区域不透明
+
+### 3.5 响应式设计
+
+**小屏幕适配(高度 < 768px)**:
+```css
+@media screen and (max-height: 768px) {
+ .import-result-dialog.el-message-box {
+ max-height: 85vh !important;
+ max-width: 90vw !important;
+ width: 90vw !important;
+ }
+
+ .import-result-dialog .el-message-box__content {
+ max-height: calc(85vh - 100px) !important;
+ padding: 10px 15px !important;
+ }
+}
+```
+
+**超小屏幕适配(宽度 < 768px)**:
+```css
+@media screen and (max-width: 768px) {
+ .import-result-dialog.el-message-box {
+ max-width: 95vw !important;
+ width: 95vw !important;
+ }
+}
+```
+
+### 3.6 错误信息格式优化
+
+```css
+.import-result-dialog .el-message-box__content p {
+ margin: 0;
+ padding: 0;
+ line-height: 1.8;
+ font-size: 14px;
+ color: #606266;
+}
+
+.import-result-dialog .el-message-box__content br {
+ display: block;
+ margin: 4px 0;
+ content: "";
+}
+```
+
+---
+
+## 4. 实施计划
+
+### 4.1 修改文件
+
+- **文件**: `ruoyi-ui/src/views/ccdiEmployee/index.vue`
+- **位置**: 第638-662行(全局样式部分)
+
+### 4.2 实施步骤
+
+1. **备份现有样式**
+ - 记录当前样式配置
+ - 保存弹窗截图作为对比基准
+
+2. **修改CSS样式**
+ - 替换全局样式部分
+ - 保持Vue组件作用域样式不变
+ - 确保新样式全局生效(弹窗挂载在body下)
+
+3. **验证不同场景**
+ - 导入全部成功(简短消息)
+ - 1-10条失败(中等长度)
+ - 10-50条失败(较长列表)
+ - 50+条失败(超长列表)
+
+4. **多屏幕尺寸测试**
+ - 1920x1080(桌面)
+ - 1366x768(笔记本)
+ - 768x1024(平板竖屏)
+ - 375x667(移动端)
+
+### 4.3 验收标准
+
+- [ ] 弹窗始终完整显示在视口内
+- [ ] 标题、内容、按钮三部分布局清晰
+- [ ] 内容区域可独立滚动
+- [ ] 确定按钮始终可见可点击
+- [ ] 滚动条样式美观且易于操作
+- [ ] 小屏幕下不出现横向滚动条
+
+---
+
+## 5. 技术要点
+
+### 5.1 为什么使用 `!important`?
+
+Element UI 的 MessageBox 组件有较高的CSS优先级,必须使用 `!important` 覆盖默认样式。
+
+### 5.2 为什么使用全局样式?
+
+`$alert` 创建的弹窗挂载在 `document.body` 下,不在 Vue 组件的作用域内,因此必须使用全局样式(非 `