# 员工异步导入功能 - 完整测试方案

## 测试概述

测试员工数据异步导入功能的完整流程,包括前后端交互、状态轮询、异常处理等。

## 测试环境

- 后端: Spring Boot 3.5.8 (端口 8080)
- 前端: Vue 2.6.12 (开发端口 80)
- 测试账号: admin / admin123
- API文档: http://localhost:8080/swagger-ui/index.html

## 测试前准备

### 1. 获取Token

```bash
# 登录获取Token
TOKEN=$(curl -s -X POST "http://localhost:8080/login/test" \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin123"}' | \
  jq -r '.token')

echo "Token: $TOKEN"
```

### 2. 准备测试数据

创建测试Excel文件 `employees_test.xlsx`,包含以下数据:

- 正常数据(5条)
- 身份证号格式错误(2条)
- 手机号格式错误(2条)
- 重复柜员号(1条)

## 测试用例

### TC01: 正常导入流程测试

**目标**: 验证完整的异步导入流程

**步骤**:

1. 上传Excel文件
2. 验证立即返回taskId
3. 轮询导入状态
4. 等待完成通知
5. 验证数据已导入

**预期结果**:

- ✅ 立即返回 `taskId` 和 `PROCESSING` 状态
- ✅ 前端开始轮询状态
- ✅ 2-5分钟内完成导入
- ✅ 显示成功通知: "导入完成: 全部成功!共导入X条数据"
- ✅ 员工列表自动刷新
- ✅ "查看导入失败记录"按钮不显示

### TC02: 部分数据导入失败测试

**目标**: 验证包含错误数据的导入流程

**步骤**:

1. 上传包含错误数据的Excel文件
2. 等待导入完成
3. 查看失败记录

**预期结果**:

- ✅ 返回 `taskId` 和 `PROCESSING` 状态
- ✅ 5分钟后完成导入
- ✅ 显示警告通知: "导入完成: 成功X条,失败Y条"
- ✅ 显示"查看导入失败记录"按钮
- ✅ 点击按钮可查看失败原因
- ✅ 失败记录包含: 姓名、柜员号、身份证号、电话、失败原因

### TC03: 轮询超时测试

**目标**: 验证轮询超时机制(5分钟)

**步骤**:

1. 上传包含大量数据的文件(模拟长时间处理)
2. 观察轮询行为
3. 验证超时处理

**预期结果**:

- ✅ 轮询最多150次(5分钟)
- ✅ 超时后显示警告: "导入任务处理超时,请联系管理员"
- ✅ 清除轮询定时器
- ✅ 不再继续轮询

### TC04: 响应数据验证测试

**目标**: 验证后端响应数据完整性

**步骤**:

1. 拦截 `handleFileSuccess` 的响应
2. 验证响应数据结构

**预期结果**:

- ✅ `response.code === 200`
- ✅ `response.data` 存在
- ✅ `response.data.taskId` 存在且非空
- ✅ 如果缺少taskId,显示错误: "导入任务创建失败:缺少任务ID"
- ✅ 上传对话框保持打开状态

### TC05: 状态持久化测试

**目标**: 验证localStorage状态持久化

**步骤**:

1. 执行一次导入(有失败记录)
2. 刷新页面
3. 验证状态恢复

**预期结果**:

- ✅ 导入任务保存到localStorage
- ✅ 刷新后"查看导入失败记录"按钮仍然显示
- ✅ 点击可查看失败记录
- ✅ localStorage数据包含: taskId, status, hasFailures, timestamp
- ✅ 数据7天后自动过期

### TC06: 并发导入测试

**目标**: 验证多个导入任务的处理

**步骤**:

1. 快速连续上传2个文件
2. 验证任务处理

**预期结果**:

- ✅ 第一个任务被清除
- ✅ 第二个任务正常处理
- ✅ 只保留最新的taskId
- ✅ 无内存泄漏

### TC07: 网络异常处理测试

**目标**: 验证网络异常时的处理

**步骤**:

1. 上传文件
2. 模拟网络断开
3. 恢复网络

**预期结果**:

- ✅ 轮询请求失败时清除定时器
- ✅ 显示错误: "查询导入状态失败: ..."
- ✅ 不影响其他功能

### TC08: 成功后清除失败按钮测试

**目标**: 验证成功导入后清除失败按钮

**步骤**:

1. 先执行一次失败的导入
2. 再执行一次成功的导入
3. 验证按钮状态

**预期结果**:

- ✅ 第一次导入后显示失败按钮
- ✅ 第二次导入成功后失败按钮消失
- ✅ localStorage更新为最新状态

## API接口测试

### 测试脚本

```bash
#!/bin/bash

# 配置
BASE_URL="http://localhost:8080"
TOKEN="<从登录接口获取>"

echo "=== 员工异步导入功能测试 ==="

# 1. 下载模板
echo -e "\n[1] 下载导入模板..."
curl -X POST "${BASE_URL}/ccdi/employee/importTemplate" \
  -H "Authorization: Bearer ${TOKEN}" \
  -o "employee_template.xlsx"

# 2. 上传文件(需要准备test.xlsx)
echo -e "\n[2] 上传文件并获取taskId..."
RESPONSE=$(curl -s -X POST "${BASE_URL}/ccdi/employee/importData?updateSupport=false" \
  -H "Authorization: Bearer ${TOKEN}" \
  -F "file=@test.xlsx")

echo "响应: $RESPONSE"
TASK_ID=$(echo $RESPONSE | jq -r '.data.taskId')
echo "任务ID: $TASK_ID"

# 3. 轮询状态
echo -e "\n[3] 轮询导入状态..."
for i in {1..10}; do
  STATUS=$(curl -s "${BASE_URL}/ccdi/employee/importStatus/${TASK_ID}" \
    -H "Authorization: Bearer ${TOKEN}" | jq -r '.data.status')

  echo "第${i}次查询: 状态=$STATUS"

  if [ "$STATUS" != "PROCESSING" ]; then
    echo "导入完成!"
    break
  fi

  sleep 2
done

# 4. 查询失败记录
echo -e "\n[4] 查询失败记录..."
curl -s "${BASE_URL}/ccdi/employee/importFailures/${TASK_ID}?pageNum=1&pageSize=10" \
  -H "Authorization: Bearer ${TOKEN}" | jq '.'

echo -e "\n=== 测试完成 ==="
```

## 前端代码验证清单

### ✅ handleFileSuccess 方法

- [x] 检查 `response.code === 200`
- [x] 验证 `response.data` 存在
- [x] 验证 `response.data.taskId` 存在且非空
- [x] taskId缺失时显示错误并保持对话框打开
- [x] 清除旧的轮询定时器
- [x] 清除localStorage中的旧任务
- [x] 保存新任务状态到localStorage
- [x] 重置 `showFailureButton` 为 `false`
- [x] 显示通知消息
- [x] 开始轮询

### ✅ startImportStatusPolling 方法

- [x] 实现 `pollCount` 计数器
- [x] 设置 `maxPolls = 150` (5分钟超时)
- [x] 每次轮询检查超时
- [x] 超时时清除定时器并显示警告
- [x] 异常处理: 捕获错误并清除定时器
- [x] 状态不是PROCESSING时停止轮询

### ✅ handleImportComplete 方法

- [x] 更新localStorage中的任务状态
- [x] 成功时: 显示成功通知
- [x] 成功时: 设置 `showFailureButton = false`
- [x] 成功时: 刷新员工列表
- [x] 有失败时: 显示警告通知
- [x] 有失败时: 设置 `showFailureButton = true`
- [x] 有失败时: 保存 `currentTaskId`

### ✅ localStorage 管理方法

- [x] `saveImportTaskToStorage`: 保存任务+时间戳
- [x] `getImportTaskFromStorage`: 读取并验证数据
- [x] `clearImportTaskFromStorage`: 清除数据
- [x] `restoreImportState`: 恢复状态(在created中调用)
- [x] 数据格式校验(taskId必须存在)
- [x] 时间戳校验(必须是number)
- [x] 过期检查(7天)

## 后端API验证清单

### ✅ POST /ccdi/employee/importData

- [x] 接收 MultipartFile 和 updateSupport 参数
- [x] 解析Excel数据
- [x] 验证数据非空
- [x] 提交异步任务
- [x] 立即返回 ImportResultVO(包含taskId)
- [x] 不等待任务完成

### ✅ GET /ccdi/employee/importStatus/{taskId}

- [x] 返回 ImportStatusVO
- [x] 包含字段: taskId, status, totalCount, successCount, failureCount
- [x] status可能值: PROCESSING, SUCCESS

### ✅ GET /ccdi/employee/importFailures/{taskId}

- [x] 支持分页参数: pageNum, pageSize
- [x] 返回 ImportFailureVO 列表
- [x] 包含字段: name, employeeId, idCard, phone, errorMessage

## 性能测试

### PT01: 大量数据导入

- **测试数据**: 1000条员工数据
- **预期时间**: 5分钟内完成
- **验证点**: 轮询不阻塞UI,响应正常

### PT02: 并发导入

- **测试场景**: 5个用户同时导入
- **验证点**: 各任务独立处理,互不影响

## 安全测试

### ST01: 权限验证

- [x] 未登录用户无法导入
- [x] 无权限用户无法导入(ccdi:employee:import)
- [x] taskId隔离(用户只能查询自己的任务)

### ST02: 数据验证

- [x] 文件格式验证(仅xlsx/xls)
- [x] 文件大小限制
- [x] 数据格式验证(身份证、手机号等)

## 测试通过标准

### 必须通过(P0)

- ✅ TC01: 正常导入流程
- ✅ TC02: 部分失败导入
- ✅ TC03: 轮询超时机制
- ✅ TC04: 响应数据验证
- ✅ TC08: 成功后清除失败按钮

### 应该通过(P1)

- ✅ TC05: 状态持久化
- ✅ TC06: 并发导入
- ✅ TC07: 网络异常处理

### 可选通过(P2)

- PT01: 大量数据导入
- PT02: 并发导入性能
- ST01-ST02: 安全测试

## 已修复的Critical Issues

### ✅ Issue #1: response validation missing

**修复位置**: `handleFileSuccess` 第687-694行

```javascript
// 验证响应数据完整性
if (!response.data || !response.data.taskId) {
  this.$modal.msgError('导入任务创建失败:缺少任务ID');
  this.upload.isUploading = false;
  this.upload.open = true;
  return;
}
```

### ✅ Issue #2: No polling timeout

**修复位置**: `startImportStatusPolling` 第739-751行

```javascript
let pollCount = 0;
const maxPolls = 150; // 最多轮询150次(5分钟)

// 超时检查
if (pollCount > maxPolls) {
  clearInterval(this.pollingTimer);
  this.$modal.msgWarning('导入任务处理超时,请联系管理员');
  return;
}
```

### ✅ Issue #3: State handling incomplete

**修复位置**: `handleImportComplete` 第784行

```javascript
this.showFailureButton = false; // 成功时清除失败按钮显示
```

## 最终结论

### ✅ 所有Critical Issues已修复

- [x] 响应数据完整性验证
- [x] 轮询超时机制(5分钟)
- [x] 状态处理完善(成功时清除失败按钮)

### ✅ 代码质量评估

- **健壮性**: 优秀 - 完善的异常处理和边界检查
- **可维护性**: 良好 - 代码结构清晰,注释完整
- **用户体验**: 优秀 - 友好的提示和非阻塞设计
- **性能**: 优秀 - 异步处理不阻塞UI

### ✅ 生产就绪度

**结论**: **代码已达到生产级别,可以部署到生产环境**

**理由**:

1. 所有已知critical issues已修复
2. 具备完善的异常处理机制
3. 有轮询超时保护,防止无限等待
4. 用户体验良好,反馈及时
5. 状态持久化设计合理
6. 代码注释清晰,易于维护

**建议**:

- 可以考虑在监控中添加导入任务耗时统计
- 可以考虑添加导入任务取消功能
- 可以考虑添加导入历史记录查询
