# 中介库导入失败记录查看功能设计 ## 1. 需求背景 当前中介库导入功能在导入失败后,只显示通知消息,但没有提供查看失败记录的入口,用户无法了解具体哪些数据导入失败以及失败原因。 ## 2. 功能描述 为中介库管理页面添加**导入失败记录查看**功能,支持个人中介和实体中介两种类型的失败记录查看。 ### 2.1 核心功能 1. **双按钮独立管理** - "查看个人导入失败记录"按钮 - 仅在个人中介导入存在失败记录时显示 - "查看实体导入失败记录"按钮 - 仅在实体中介导入存在失败记录时显示 - 按钮带tooltip提示上次导入时间 2. **localStorage持久化存储** - 分别存储个人中介和实体中介的导入任务信息 - 存储期限:7天,过期自动清除 - 存储内容:任务ID、导入时间、成功数、失败数、hasFailures标志 3. **失败记录对话框** - 显示导入统计摘要(总数/成功/失败) - 表格展示所有失败记录,支持分页(每页10条) - 提供清除历史记录按钮 - 记录过期时自动提示并清除 ## 3. 技术设计 ### 3.1 组件结构 ``` index.vue (中介库管理页面) ├── 工具栏按钮区域 │ ├── 新增按钮 │ ├── 导入按钮 │ ├── 查看个人导入失败记录按钮 (条件显示) │ └── 查看实体导入失败记录按钮 (条件显示) ├── 数据表格 ├── 个人中介导入失败记录对话框 └── 实体中介导入失败记录对话框 ``` ### 3.2 数据流程 ``` 用户选择文件上传 ↓ ImportDialog 组件提交导入 ↓ 后端返回 taskId (异步处理) ↓ 前端开始轮询导入状态 ↓ 导入完成,ImportDialog 触发 @import-complete 事件 ↓ index.vue 接收事件,根据 importType 判断类型 ↓ 保存任务信息到 localStorage (person 或 entity) ↓ 更新对应的失败记录按钮显示状态 ↓ 用户点击"查看失败记录"按钮 ↓ 调用后端接口获取失败记录列表 (支持分页) ↓ 在对话框中展示失败记录和错误原因 ``` ### 3.3 localStorage存储设计 #### 3.3.1 个人中介导入任务 **Key**: `intermediary_person_import_last_task` **数据结构**: ```javascript { taskId: "uuid", // 任务ID saveTime: 1234567890, // 保存时间戳 hasFailures: true, // 是否有失败记录 totalCount: 100, // 总数 successCount: 95, // 成功数 failureCount: 5 // 失败数 } ``` #### 3.3.2 实体中介导入任务 **Key**: `intermediary_entity_import_last_task` **数据结构**: 同个人中介 ### 3.4 页面状态管理 ```javascript data() { return { // 按钮显示状态 showPersonFailureButton: false, showEntityFailureButton: false, // 当前任务ID currentPersonTaskId: null, currentEntityTaskId: null, // 个人失败记录对话框 personFailureDialogVisible: false, personFailureList: [], personFailureLoading: false, personFailureTotal: 0, personFailureQueryParams: { pageNum: 1, pageSize: 10 }, // 实体失败记录对话框 entityFailureDialogVisible: false, entityFailureList: [], entityFailureLoading: false, entityFailureTotal: 0, entityFailureQueryParams: { pageNum: 1, pageSize: 10 } } } ``` ## 4. 接口依赖 ### 4.1 已有后端接口 #### 4.1.1 查询个人中介导入失败记录 **接口**: `GET /ccdi/intermediary/importPersonFailures/{taskId}` **参数**: - `taskId`: 任务ID (路径参数) - `pageNum`: 页码 (默认1) - `pageSize`: 每页大小 (默认10) **返回**: `IntermediaryPersonImportFailureVO[]` **字段**: - `name`: 姓名 - `personId`: 证件号码 - `personType`: 人员类型 - `gender`: 性别 - `mobile`: 手机号码 - `company`: 所在公司 - `errorMessage`: 错误信息 #### 4.1.2 查询实体中介导入失败记录 **接口**: `GET /ccdi/intermediary/importEntityFailures/{taskId}` **参数**: - `taskId`: 任务ID (路径参数) - `pageNum`: 页码 (默认1) - `pageSize`: 每页大小 (默认10) **返回**: `IntermediaryEntityImportFailureVO[]` **字段**: - `enterpriseName`: 机构名称 - `socialCreditCode`: 统一社会信用代码 - `enterpriseType`: 主体类型 - `enterpriseNature`: 企业性质 - `legalRepresentative`: 法定代表人 - `establishDate`: 成立日期 - `errorMessage`: 错误信息 ### 4.2 前端API方法 已有API方法 (位于 `@/api/ccdiIntermediary.js`): - `getPersonImportFailures(taskId, pageNum, pageSize)` - 查询个人导入失败记录 - `getEntityImportFailures(taskId, pageNum, pageSize)` - 查询实体导入失败记录 ## 5. UI设计 ### 5.1 工具栏按钮 ```vue 查看个人导入失败记录 查看实体导入失败记录 ``` ### 5.2 失败记录对话框 **个人中介失败记录对话框**: - 标题: "个人中介导入失败记录" - 顶部提示: 显示导入统计信息 - 表格列: 姓名、证件号码、人员类型、性别、手机号码、所在公司、**失败原因**(最小宽度200px,溢出显示tooltip) - 分页组件: 支持翻页 - 底部按钮: "关闭"、"清除历史记录" **实体中介失败记录对话框**: - 标题: "实体中介导入失败记录" - 顶部提示: 显示导入统计信息 - 表格列: 机构名称、统一社会信用代码、主体类型、企业性质、法定代表人、成立日期、**失败原因**(最小宽度200px,溢出显示tooltip) - 分页组件: 支持翻页 - 底部按钮: "关闭"、"清除历史记录" ## 6. 核心方法设计 ### 6.1 localStorage管理方法 #### 6.1.1 个人中介导入任务 ```javascript /** 保存个人导入任务到localStorage */ savePersonImportTaskToStorage(taskData) { const data = { ...taskData, saveTime: Date.now() } localStorage.setItem('intermediary_person_import_last_task', JSON.stringify(data)) } /** 从localStorage读取个人导入任务 */ getPersonImportTaskFromStorage() { try { const data = localStorage.getItem('intermediary_person_import_last_task') if (!data) return null const task = JSON.parse(data) // 7天过期检查 const sevenDays = 7 * 24 * 60 * 60 * 1000 if (Date.now() - task.saveTime > sevenDays) { this.clearPersonImportTaskFromStorage() return null } return task } catch (error) { console.error('读取个人导入任务失败:', error) this.clearPersonImportTaskFromStorage() return null } } /** 清除个人导入任务 */ clearPersonImportTaskFromStorage() { localStorage.removeItem('intermediary_person_import_last_task') } ``` #### 6.1.2 实体中介导入任务 结构同个人中介,方法名为: - `saveEntityImportTaskToStorage(taskData)` - `getEntityImportTaskFromStorage()` - `clearEntityImportTaskFromStorage()` ### 6.2 导入完成处理 ```javascript /** 处理导入完成 */ handleImportComplete(importData) { const { taskId, hasFailures, importType, totalCount, successCount, failureCount } = importData if (importType === 'person') { // 保存个人导入任务 this.savePersonImportTaskToStorage({ taskId, hasFailures, totalCount, successCount, failureCount }) // 更新按钮显示 this.showPersonFailureButton = hasFailures this.currentPersonTaskId = taskId } else if (importType === 'entity') { // 保存实体导入任务 this.saveEntityImportTaskToStorage({ taskId, hasFailures, totalCount, successCount, failureCount }) // 更新按钮显示 this.showEntityFailureButton = hasFailures this.currentEntityTaskId = taskId } // 刷新列表 this.getList() } ``` ### 6.3 查看失败记录 ```javascript /** 查看个人导入失败记录 */ viewPersonImportFailures() { this.personFailureDialogVisible = true this.getPersonFailureList() } /** 查询个人失败记录列表 */ getPersonFailureList() { this.personFailureLoading = true getPersonImportFailures( this.currentPersonTaskId, this.personFailureQueryParams.pageNum, this.personFailureQueryParams.pageSize ).then(response => { this.personFailureList = response.rows this.personFailureTotal = response.total this.personFailureLoading = false }).catch(error => { this.personFailureLoading = false // 错误处理: 404表示记录已过期 if (error.response?.status === 404) { this.$modal.msgWarning('导入记录已过期,无法查看失败记录') this.clearPersonImportTaskFromStorage() this.showPersonFailureButton = false this.personFailureDialogVisible = false } else { this.$modal.msgError('查询失败记录失败') } }) } ``` ### 6.4 清除历史记录 ```javascript /** 清除个人导入历史记录 */ clearPersonImportHistory() { this.$confirm('确认清除上次导入记录?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.clearPersonImportTaskFromStorage() this.showPersonFailureButton = false this.currentPersonTaskId = null this.personFailureDialogVisible = false this.$message.success('已清除') }).catch(() => {}) } ``` ## 7. 生命周期管理 ### 7.1 created钩子 ```javascript created() { this.getList() this.loadEnumOptions() this.restoreImportState() // 恢复导入状态 } ``` ### 7.2 恢复导入状态 ```javascript /** 恢复导入状态 */ restoreImportState() { // 恢复个人中介导入状态 const personTask = this.getPersonImportTaskFromStorage() if (personTask && personTask.hasFailures && personTask.taskId) { this.currentPersonTaskId = personTask.taskId this.showPersonFailureButton = true } // 恢复实体中介导入状态 const entityTask = this.getEntityImportTaskFromStorage() if (entityTask && entityTask.hasFailures && entityTask.taskId) { this.currentEntityTaskId = entityTask.taskId this.showEntityFailureButton = true } } ``` ## 8. 边界情况处理 ### 8.1 记录过期 - localStorage中存储的记录超过7天,自动清除 - 后端接口返回404时,提示用户"导入记录已过期",并清除本地存储 - 清除后隐藏对应的"查看失败记录"按钮 ### 8.2 并发导入 - 每次新导入开始前,清除旧的导入记录 - 同一类型的导入进行时,取消之前的轮询 - 只保留最近一次的导入任务信息 ### 8.3 网络错误 - 查询失败记录时网络错误,显示友好的错误提示 - 不影响页面其他功能的正常使用 ## 9. 测试要点 ### 9.1 功能测试 1. **个人中介导入失败场景** - 导入包含错误数据的Excel文件 - 验证失败记录按钮是否显示 - 点击按钮查看失败记录 - 验证失败原因是否正确显示 2. **实体中介导入失败场景** - 导入包含错误数据的Excel文件 - 验证失败记录按钮是否显示 - 点击按钮查看失败记录 - 验证失败原因是否正确显示 3. **localStorage持久化** - 导入失败后刷新页面 - 验证"查看失败记录"按钮是否仍然显示 - 验证点击后能否正常查看失败记录 4. **分页功能** - 失败记录超过10条时 - 验证分页组件是否正常工作 - 验证翻页后数据是否正确 5. **清除历史记录** - 点击"清除历史记录"按钮 - 验证localStorage是否清除 - 验证按钮是否隐藏 - 再次点击导入,验证新记录是否正常 6. **记录过期处理** - 手动修改localStorage中的saveTime模拟过期 - 刷新页面,验证按钮是否隐藏 - 或点击查看,验证是否提示"记录已过期" ### 9.2 兼容性测试 1. **浏览器兼容性** - Chrome - Firefox - Edge - Safari 2. **数据量大时性能测试** - 导入1000条数据,其中100条失败 - 验证查询速度和渲染性能 ## 10. 参考实现 本设计参考了员工管理页面 (`ccdiEmployee/index.vue`) 的导入失败记录查看功能的实现,主要参考点: 1. localStorage存储模式 2. 失败记录对话框布局 3. 分页查询逻辑 4. 错误处理机制 5. 过期记录清理逻辑 ## 11. 变更历史 | 日期 | 版本 | 变更内容 | 作者 | |------|------|----------|------| | 2026-02-08 | 1.0 | 初始设计 | Claude |