# 解析任务管理类API接口操作说明文档 > **版本**: v1.0 > **更新时间**: 2025-01-18 > **适用对象**: 前端开发工程师 ## 📋 目录 1. [接口概览](#接口概览) 2. [通用说明](#通用说明) 3. [接口详细说明](#接口详细说明) - [1. 获取解析任务列表](#1-获取解析任务列表) - [2. 获取解析任务详情](#2-获取解析任务详情) - [3. 新增解析任务](#3-新增解析任务) - [4. 执行解析任务](#4-执行解析任务) - [5. 处理解析结果](#5-处理解析结果) 4. [前端集成示例](#前端集成示例) 5. [错误处理](#错误处理) 6. [最佳实践](#最佳实践) --- ## 接口概览 | 序号 | 接口名称 | HTTP方法 | 接口路径 | 功能描述 | |------|----------|----------|----------|----------| | 1 | 获取解析任务列表 | GET | `/api/data-parse/get-parse-tasks` | 分页查询解析任务列表,支持过滤 | | 2 | 获取解析任务详情 | GET | `/api/data-parse/get-parse-task-detail` | 根据任务名称获取详细信息 | | 3 | 新增解析任务 | POST | `/api/data-parse/add-parse-task` | 创建新的解析任务并上传文件 | | 4 | 执行解析任务 | POST | `/api/data-parse/execute-parse-task` | 执行指定的批量解析任务 | | 5 | 处理解析结果 | POST | `/api/data-parse/add-parsed-talents` | 将解析结果写入人才数据库 | --- ## 通用说明 ### 🌐 服务器信息 - **开发环境**: `http://localhost:5000` - **生产环境**: `http://192.168.3.143:5000` - **API前缀**: `/api/data-parse` ### 🔒 认证方式 - 当前版本暂无认证要求 - 后续版本可能需要Bearer Token ### 📊 响应格式 所有接口均返回统一的JSON格式: ```json { "success": boolean, // 请求是否成功 "message": string, // 响应消息 "data": object | null // 响应数据 } ``` ### 📋 任务类型说明 | 任务类型 | 代码值 | 支持文件格式 | 存储目录 | 说明 | |----------|--------|--------------|----------|------| | 名片 | `"名片"` | JPG, PNG | `talent_photos/` | 名片图片解析 | | 简历 | `"简历"` | PDF | `resume_files/` | 简历文档解析 | | 新任命 | `"新任命"` | MD | `appointment_files/` | 任命文档解析 | | 招聘 | `"招聘"` | 无需文件 | 无 | 数据库记录处理 | | 杂项 | `"杂项"` | 任意格式 | `misc_files/` | 其他类型文件 | --- ## 接口详细说明 ### 1. 获取解析任务列表 #### 📝 基本信息 - **接口路径**: `GET /api/data-parse/get-parse-tasks` - **功能**: 分页查询解析任务列表,支持按任务类型和状态过滤 - **内容类型**: `application/json` #### 📥 请求参数 | 参数名 | 类型 | 必填 | 默认值 | 说明 | 示例值 | |--------|------|------|--------|------|--------| | `page` | integer | 否 | 1 | 页码,从1开始 | `1` | | `per_page` | integer | 否 | 10 | 每页记录数,最大100 | `20` | | `task_type` | string | 否 | - | 任务类型过滤 | `"名片"` | | `task_status` | string | 否 | - | 任务状态过滤 | `"待解析"` | #### 📤 响应结果 ```json { "success": true, "message": "获取解析任务列表成功", "data": { "tasks": [ { "id": 123, "task_name": "parse_task_20250118_a1b2c3d4", "task_status": "待解析", "task_type": "名片", "task_source": { "minio_paths_json": [ "talent_photos/talent_photo_20250118_143012_a1b2c3d4.jpg" ], "upload_time": "2025-01-18T14:30:25.123456" }, "collection_count": 5, "parse_count": 0, "parse_result": null, "created_at": "2025-01-18 14:30:25", "created_by": "api_user", "updated_at": "2025-01-18 14:30:25", "updated_by": "api_user" } ], "pagination": { "page": 1, "per_page": 10, "total": 25, "pages": 3, "has_next": true, "has_prev": false } } } ``` #### 🎯 前端调用示例 ```javascript // 使用fetch API async function getParseTaskList(page = 1, perPage = 10, taskType = null, taskStatus = null) { const params = new URLSearchParams(); params.append('page', page); params.append('per_page', perPage); if (taskType) params.append('task_type', taskType); if (taskStatus) params.append('task_status', taskStatus); try { const response = await fetch(`/api/data-parse/get-parse-tasks?${params}`, { method: 'GET', headers: { 'Content-Type': 'application/json', } }); const result = await response.json(); if (result.success) { console.log('任务列表获取成功:', result.data); return result.data; } else { console.error('获取失败:', result.message); throw new Error(result.message); } } catch (error) { console.error('请求异常:', error); throw error; } } // 使用示例 getParseTaskList(1, 20, '名片', '待解析') .then(data => { console.log('总任务数:', data.pagination.total); console.log('任务列表:', data.tasks); }) .catch(error => { console.error('获取任务列表失败:', error); }); ``` #### 📊 状态码说明 | HTTP状态码 | 业务状态 | 说明 | |------------|----------|------| | 200 | success: true | 查询成功 | | 400 | success: false | 请求参数错误 | | 500 | success: false | 服务器内部错误 | --- ### 2. 获取解析任务详情 #### 📝 基本信息 - **接口路径**: `GET /api/data-parse/get-parse-task-detail` - **功能**: 根据任务名称获取解析任务的详细信息 - **内容类型**: `application/json` #### 📥 请求参数 | 参数名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | `task_name` | string | 是 | 任务名称 | `"parse_task_20250118_a1b2c3d4"` | #### 📤 响应结果 ```json { "success": true, "message": "成功获取任务 parse_task_20250118_a1b2c3d4 的详细信息", "data": { "id": 123, "task_name": "parse_task_20250118_a1b2c3d4", "task_status": "解析完成", "task_type": "名片", "task_source": { "minio_paths_json": [ "talent_photos/talent_photo_20250118_143012_a1b2c3d4.jpg", "talent_photos/talent_photo_20250118_143015_b2c3d4e5.jpg" ], "upload_time": "2025-01-18T14:30:25.123456" }, "collection_count": 2, "parse_count": 2, "parse_result": { "summary": { "total_files": 2, "success_count": 2, "failed_count": 0, "success_rate": 100.0 }, "results": [ { "index": 0, "success": true, "data": { "name_zh": "张三", "title_zh": "技术总监", "hotel_zh": "北京万豪酒店", "mobile": "13800138000", "email": "zhangsan@marriott.com" } } ] }, "created_at": "2025-01-18 14:30:25", "created_by": "api_user", "updated_at": "2025-01-18 15:45:30", "updated_by": "system" } } ``` #### 🎯 前端调用示例 ```javascript // 使用fetch API async function getParseTaskDetail(taskName) { if (!taskName) { throw new Error('任务名称不能为空'); } const params = new URLSearchParams(); params.append('task_name', taskName); try { const response = await fetch(`/api/data-parse/get-parse-task-detail?${params}`, { method: 'GET', headers: { 'Content-Type': 'application/json', } }); const result = await response.json(); if (result.success) { console.log('任务详情获取成功:', result.data); return result.data; } else { console.error('获取失败:', result.message); throw new Error(result.message); } } catch (error) { console.error('请求异常:', error); throw error; } } // 使用示例 getParseTaskDetail('parse_task_20250118_a1b2c3d4') .then(taskDetail => { console.log('任务状态:', taskDetail.task_status); console.log('解析结果:', taskDetail.parse_result); }) .catch(error => { console.error('获取任务详情失败:', error); }); ``` #### 📊 状态码说明 | HTTP状态码 | 业务状态 | 说明 | |------------|----------|------| | 200 | success: true | 查询成功 | | 400 | success: false | 请求参数错误 | | 404 | success: false | 任务不存在 | | 500 | success: false | 服务器内部错误 | --- ### 3. 新增解析任务 #### 📝 基本信息 - **接口路径**: `POST /api/data-parse/add-parse-task` - **功能**: 创建新的解析任务并上传文件到MinIO存储 - **内容类型**: `multipart/form-data` #### 📥 请求参数 | 参数名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | `task_type` | string | 是 | 任务类型 | `"名片"` | | `files` | File[] | 否* | 文件数组 | `[file1.jpg, file2.png]` | | `created_by` | string | 否 | 创建者 | `"frontend_user"` | > **注意**: 除"招聘"类型外,其他类型必须上传文件 #### 📤 响应结果 ```json { "success": true, "message": "解析任务创建成功,所有文件上传完成", "data": { "task_info": { "id": 124, "task_name": "parse_task_20250118_b2c3d4e5", "task_status": "待解析", "task_type": "名片", "task_source": { "minio_paths_json": [ "talent_photos/talent_photo_20250118_143012_a1b2c3d4.jpg" ], "upload_time": "2025-01-18T14:30:25.123456" }, "collection_count": 2, "parse_count": 0, "parse_result": null, "created_by": "frontend_user", "updated_by": "frontend_user", "created_at": "2025-01-18 14:30:25", "updated_at": "2025-01-18 14:30:25" }, "upload_summary": { "task_type": "名片", "total_files": 2, "uploaded_count": 2, "failed_count": 0, "uploaded_files": [ { "original_filename": "business_card1.jpg", "minio_path": "talent_photos/talent_photo_20250118_143012_a1b2c3d4.jpg", "relative_path": "talent_photos/talent_photo_20250118_143012_a1b2c3d4.jpg", "file_size": 256000 } ], "failed_uploads": [] } } } ``` #### 🎯 前端调用示例 ```javascript // 使用fetch API和FormData async function createParseTask(taskType, files, createdBy = 'frontend_user') { const formData = new FormData(); // 添加任务类型 formData.append('task_type', taskType); // 添加创建者 formData.append('created_by', createdBy); // 添加文件(如果有的话) if (files && files.length > 0) { for (let i = 0; i < files.length; i++) { formData.append('files', files[i]); } } try { const response = await fetch('/api/data-parse/add-parse-task', { method: 'POST', body: formData // 注意:不要设置Content-Type,让浏览器自动设置multipart/form-data }); const result = await response.json(); if (result.success) { console.log('任务创建成功:', result.data); return result.data; } else { console.error('创建失败:', result.message); throw new Error(result.message); } } catch (error) { console.error('请求异常:', error); throw error; } } // HTML文件上传示例 function setupFileUpload() { const fileInput = document.getElementById('fileInput'); const taskTypeSelect = document.getElementById('taskTypeSelect'); const uploadBtn = document.getElementById('uploadBtn'); uploadBtn.addEventListener('click', async () => { const taskType = taskTypeSelect.value; const files = fileInput.files; if (!taskType) { alert('请选择任务类型'); return; } if (taskType !== '招聘' && files.length === 0) { alert('请选择要上传的文件'); return; } try { const result = await createParseTask(taskType, files); alert(`任务创建成功!任务ID: ${result.task_info.id}`); // 清空文件选择 fileInput.value = ''; } catch (error) { alert(`任务创建失败: ${error.message}`); } }); } // 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', setupFileUpload); ``` #### 🌐 HTML示例 ```html 创建解析任务
``` #### 📊 状态码说明 | HTTP状态码 | 业务状态 | 说明 | |------------|----------|------| | 200 | success: true | 所有文件上传成功,任务创建成功 | | 206 | success: true | 部分文件上传成功,任务创建成功 | | 400 | success: false | 请求参数错误 | | 500 | success: false | 服务器内部错误 | --- ### 4. 执行解析任务 #### 📝 基本信息 - **接口路径**: `POST /api/data-parse/execute-parse-task` - **功能**: 根据任务类型执行相应的批量处理函数 - **内容类型**: `application/json` #### 📥 请求参数 | 参数名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | `task_type` | string | 是 | 任务类型 | `"名片"` | | `data` | array | 是 | 数据列表,格式因任务类型而异 | `["path1.jpg", "path2.jpg"]` | | `publish_time` | string | 否* | 发布时间(仅新任命任务需要) | `"2025-01-18"` | | `process_type` | string | 否 | 处理类型(仅杂项任务) | `"table"` | | `id` | integer | 是 | 解析任务ID | `123` | > **注意**: 新任命任务必须提供`publish_time`参数 #### 📋 不同任务类型的data格式 | 任务类型 | data格式 | 示例 | |----------|----------|------| | 名片 | MinIO路径数组 | `["talent_photos/card1.jpg", "talent_photos/card2.jpg"]` | | 简历 | PDF文件路径数组 | `["resume_files/resume1.pdf", "resume_files/resume2.pdf"]` | | 新任命 | Markdown文件路径数组 | `["appointment_files/appointment1.md"]` | | 招聘 | 招聘数据对象数组 | `[{"name": "张三", "position": "经理"}]` | | 杂项 | 文件路径数组 | `["misc_files/file1.xlsx", "misc_files/file2.docx"]` | #### 📤 响应结果 ```json { "success": true, "message": "批量处理完成,全部 2 个文件处理成功", "data": { "summary": { "total_files": 2, "success_count": 2, "failed_count": 0, "success_rate": 100.0 }, "results": [ { "index": 0, "filename": "card1.jpg", "success": true, "error": null, "data": { "name_zh": "张三", "title_zh": "技术总监", "hotel_zh": "北京万豪酒店", "mobile": "13800138000", "email": "zhangsan@marriott.com", "career_path": [ { "date": "2025-01-18", "hotel_zh": "北京万豪酒店", "title_zh": "技术总监", "source": "business_card" } ] }, "message": "处理成功" } ], "processed_time": "2025-01-18T15:30:45.123456" } } ``` #### 🎯 前端调用示例 ```javascript // 执行解析任务 async function executeParseTask(taskType, data, taskId, publishTime = null, processType = 'table') { const requestBody = { task_type: taskType, data: data, id: taskId }; // 新任命任务需要发布时间 if (taskType === '新任命' && publishTime) { requestBody.publish_time = publishTime; } // 杂项任务可以指定处理类型 if (taskType === '杂项') { requestBody.process_type = processType; } try { const response = await fetch('/api/data-parse/execute-parse-task', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestBody) }); const result = await response.json(); if (result.success) { console.log('解析任务执行成功:', result.data); return result.data; } else { console.error('执行失败:', result.message); throw new Error(result.message); } } catch (error) { console.error('请求异常:', error); throw error; } } // 使用示例 const taskData = [ "talent_photos/talent_photo_20250118_143012_a1b2c3d4.jpg", "talent_photos/talent_photo_20250118_143015_b2c3d4e5.jpg" ]; executeParseTask('名片', taskData, 123) .then(result => { console.log('处理结果:', result); // 检查处理统计 const summary = result.summary; console.log(`总共${summary.total_files}个文件,成功${summary.success_count}个,失败${summary.failed_count}个`); // 处理每个结果 result.results.forEach((item, index) => { if (item.success) { console.log(`第${index + 1}个文件处理成功:`, item.data); } else { console.error(`第${index + 1}个文件处理失败:`, item.error); } }); }) .catch(error => { console.error('解析任务执行失败:', error); }); // 新任命任务示例 const appointmentData = ["appointment_files/appointment_20250118.md"]; executeParseTask('新任命', appointmentData, 124, '2025-01-18') .then(result => { console.log('新任命解析完成:', result); }) .catch(error => { console.error('新任命解析失败:', error); }); ``` #### 📊 状态码说明 | HTTP状态码 | 业务状态 | 说明 | |------------|----------|------| | 200 | success: true | 全部处理成功 | | 206 | success: true | 部分处理成功 | | 400 | success: false | 请求参数错误 | | 500 | success: false | 服务器内部错误 | --- ### 5. 处理解析结果 #### 📝 基本信息 - **接口路径**: `POST /api/data-parse/add-parsed-talents` - **功能**: 处理execute-parse-task API的响应数据,将人才信息写入business_cards表 - **内容类型**: `application/json` #### 📥 请求参数 请求体为execute-parse-task API的完整返回数据: ```json { "success": true, "message": "处理完成", "data": { "summary": { "total_files": 5, "success_count": 4, "failed_count": 1, "success_rate": 80.0 }, "results": [ { "index": 0, "success": true, "data": { "name_zh": "张三", "title_zh": "经理", "hotel_zh": "某酒店", "image_path": "talent_photos/image1.jpg" } } ], "processed_time": "2025-01-18T10:30:00" } } ``` #### 📤 响应结果 ```json { "success": true, "message": "批量处理完成,全部 4 条人才数据写入成功", "data": { "summary": { "total_files": 4, "success_count": 4, "failed_count": 0, "success_rate": 100.0, "original_summary": { "total_files": 5, "success_count": 4, "failed_count": 1, "success_rate": 80.0 } }, "results": [ { "index": 0, "original_index": 0, "success": true, "error": null, "data": { "id": 1001, "name_zh": "张三", "action": "created", "message": "成功创建新的人才记录" }, "message": "成功处理人员: 张三" } ], "processed_time": "2025-01-18T16:45:30.789012", "original_api_response": { // 保留原始API响应数据用于调试 } } } ``` #### 🎯 前端调用示例 ```javascript // 处理解析结果 async function processParseResults(executeTaskResponse) { if (!executeTaskResponse || typeof executeTaskResponse !== 'object') { throw new Error('API响应数据格式错误'); } try { const response = await fetch('/api/data-parse/add-parsed-talents', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(executeTaskResponse) }); const result = await response.json(); if (result.success) { console.log('解析结果处理成功:', result.data); return result.data; } else { console.error('处理失败:', result.message); throw new Error(result.message); } } catch (error) { console.error('请求异常:', error); throw error; } } // 完整的解析流程示例 async function completeParseWorkflow(taskType, data, taskId, publishTime = null) { try { // 第一步:执行解析任务 console.log('步骤1: 执行解析任务...'); const executeResult = await executeParseTask(taskType, data, taskId, publishTime); // 第二步:处理解析结果 console.log('步骤2: 处理解析结果...'); const processResult = await processParseResults(executeResult); // 第三步:显示最终结果 console.log('解析流程完成!'); console.log('原始解析统计:', executeResult.summary); console.log('数据写入统计:', processResult.summary); return { executeResult, processResult }; } catch (error) { console.error('解析流程失败:', error); throw error; } } // 使用示例 const taskData = ["talent_photos/card1.jpg", "talent_photos/card2.jpg"]; completeParseWorkflow('名片', taskData, 123) .then(results => { const { executeResult, processResult } = results; // 显示处理统计 console.log(`原始解析: ${executeResult.summary.success_count}/${executeResult.summary.total_files} 成功`); console.log(`数据写入: ${processResult.summary.success_count}/${processResult.summary.total_files} 成功`); // 显示详细结果 processResult.results.forEach((item, index) => { if (item.success) { console.log(`人员${index + 1}: ${item.message}`); } else { console.error(`人员${index + 1}: ${item.error}`); } }); }) .catch(error => { console.error('完整解析流程失败:', error); }); ``` #### 📊 状态码说明 | HTTP状态码 | 业务状态 | 说明 | |------------|----------|------| | 200 | success: true | 全部处理成功 | | 206 | success: true | 部分处理成功 | | 400 | success: false | 请求参数错误 | | 500 | success: false | 服务器内部错误 | --- ## 前端集成示例 ### 🎨 Vue.js 组件示例 ```vue ``` ### 🔧 工具类封装 ```javascript // parseTaskAPI.js - API调用工具类 class ParseTaskAPI { constructor(baseURL = '/api/data-parse') { this.baseURL = baseURL; } // 通用请求方法 async request(url, options = {}) { const fullURL = `${this.baseURL}${url}`; try { const response = await fetch(fullURL, { headers: { 'Content-Type': 'application/json', ...options.headers }, ...options }); const result = await response.json(); if (result.success) { return result.data; } else { throw new Error(result.message); } } catch (error) { console.error(`API请求失败: ${fullURL}`, error); throw error; } } // GET请求(用于查询类接口) async get(url, params = {}) { const queryString = new URLSearchParams(params).toString(); const fullURL = queryString ? `${url}?${queryString}` : url; return this.request(fullURL, { method: 'GET' }); } // POST请求(用于操作类接口) async post(url, data) { return this.request(url, { method: 'POST', body: JSON.stringify(data) }); } // FormData POST请求(用于文件上传) async postFormData(url, formData) { const fullURL = `${this.baseURL}${url}`; try { const response = await fetch(fullURL, { method: 'POST', body: formData }); const result = await response.json(); if (result.success) { return result.data; } else { throw new Error(result.message); } } catch (error) { console.error(`FormData请求失败: ${fullURL}`, error); throw error; } } // 1. 获取解析任务列表 async getTaskList(page = 1, perPage = 10, taskType = null, taskStatus = null) { const params = { page, per_page: perPage }; if (taskType) params.task_type = taskType; if (taskStatus) params.task_status = taskStatus; return this.get('/get-parse-tasks', params); } // 2. 获取解析任务详情 async getTaskDetail(taskName) { if (!taskName) { throw new Error('任务名称不能为空'); } return this.get('/get-parse-task-detail', { task_name: taskName }); } // 3. 新增解析任务 async createTask(taskType, files = [], createdBy = 'api_user') { const formData = new FormData(); formData.append('task_type', taskType); formData.append('created_by', createdBy); if (files && files.length > 0) { for (let i = 0; i < files.length; i++) { formData.append('files', files[i]); } } return this.postFormData('/add-parse-task', formData); } // 4. 执行解析任务 async executeTask(taskType, data, taskId, publishTime = null, processType = 'table') { const requestBody = { task_type: taskType, data: data, id: taskId }; if (taskType === '新任命' && publishTime) { requestBody.publish_time = publishTime; } if (taskType === '杂项') { requestBody.process_type = processType; } return this.post('/execute-parse-task', requestBody); } // 5. 处理解析结果 async processResults(executeTaskResponse) { if (!executeTaskResponse || typeof executeTaskResponse !== 'object') { throw new Error('API响应数据格式错误'); } return this.post('/add-parsed-talents', executeTaskResponse); } // 组合方法:完整的解析流程 async completeParseWorkflow(taskType, data, taskId, publishTime = null) { try { // 执行解析任务 const executeResult = await this.executeTask(taskType, data, taskId, publishTime); // 处理解析结果 const processResult = await this.processResults(executeResult); return { executeResult, processResult }; } catch (error) { console.error('完整解析流程失败:', error); throw error; } } } // 导出实例 export default new ParseTaskAPI(); // 使用示例: // import parseTaskAPI from './parseTaskAPI.js'; // // // 获取任务列表 // const taskList = await parseTaskAPI.getTaskList(1, 20, '名片'); // // // 创建任务 // const createResult = await parseTaskAPI.createTask('名片', files); // // // 执行完整流程 // const result = await parseTaskAPI.completeParseWorkflow('名片', data, taskId); ``` --- ## 错误处理 ### 🚨 常见错误类型 | 错误类型 | HTTP状态码 | 错误信息示例 | 处理建议 | |----------|------------|--------------|----------| | 参数错误 | 400 | `"缺少task_type参数"` | 检查请求参数完整性 | | 文件格式错误 | 400 | `"不支持的文件格式"` | 检查文件类型是否匹配任务类型 | | 任务不存在 | 404 | `"未找到任务名称为 xxx 的记录"` | 确认任务名称正确 | | 服务器错误 | 500 | `"数据库连接失败"` | 联系后端开发人员 | | 部分成功 | 206 | `"部分文件上传成功"` | 检查失败的文件,重新上传 | ### 🛠️ 错误处理最佳实践 ```javascript // 统一错误处理函数 function handleAPIError(error, context = '') { console.error(`${context}失败:`, error); // 根据错误类型给出不同的用户提示 if (error.message.includes('网络')) { return '网络连接异常,请检查网络后重试'; } else if (error.message.includes('参数')) { return '请求参数错误,请检查输入信息'; } else if (error.message.includes('权限')) { return '权限不足,请联系管理员'; } else if (error.message.includes('不存在')) { return '请求的资源不存在'; } else { return `操作失败: ${error.message}`; } } // 带重试机制的API调用 async function apiCallWithRetry(apiFunction, maxRetries = 3, delay = 1000) { for (let i = 0; i < maxRetries; i++) { try { return await apiFunction(); } catch (error) { if (i === maxRetries - 1) { throw error; } // 如果是网络错误或服务器错误,等待后重试 if (error.message.includes('fetch') || error.message.includes('500')) { console.log(`第${i + 1}次重试,${delay}ms后重新请求...`); await new Promise(resolve => setTimeout(resolve, delay)); delay *= 2; // 指数退避 } else { throw error; // 其他错误直接抛出 } } } } // 使用示例 try { const result = await apiCallWithRetry( () => parseTaskAPI.getTaskList(1, 10), 3, 1000 ); console.log('获取任务列表成功:', result); } catch (error) { const userMessage = handleAPIError(error, '获取任务列表'); alert(userMessage); } ``` --- ## 最佳实践 ### 🎯 前端开发建议 1. **参数验证** ```javascript // 在调用API前进行客户端验证 function validateTaskType(taskType) { const validTypes = ['名片', '简历', '新任命', '招聘', '杂项']; if (!validTypes.includes(taskType)) { throw new Error(`无效的任务类型: ${taskType}`); } } function validateFiles(files, taskType) { if (taskType === '招聘') { return; // 招聘任务不需要文件 } if (!files || files.length === 0) { throw new Error('请选择要上传的文件'); } // 文件格式验证 const allowedFormats = { '名片': ['jpg', 'jpeg', 'png'], '简历': ['pdf'], '新任命': ['md'], '杂项': ['*'] // 支持所有格式 }; const formats = allowedFormats[taskType]; if (formats && !formats.includes('*')) { files.forEach(file => { const ext = file.name.split('.').pop().toLowerCase(); if (!formats.includes(ext)) { throw new Error(`${taskType}任务不支持${ext}格式文件`); } }); } } ``` 2. **进度显示** ```javascript // 文件上传进度显示 function showUploadProgress(current, total) { const percentage = Math.round((current / total) * 100); console.log(`上传进度: ${current}/${total} (${percentage}%)`); // 更新UI进度条 updateProgressBar(percentage); } // 解析进度显示 function showParseProgress(results) { const completed = results.filter(r => r.success || r.error).length; const total = results.length; const percentage = Math.round((completed / total) * 100); console.log(`解析进度: ${completed}/${total} (${percentage}%)`); } ``` 3. **缓存策略** ```javascript // 任务列表缓存 class TaskListCache { constructor(ttl = 5 * 60 * 1000) { // 5分钟TTL this.cache = new Map(); this.ttl = ttl; } getKey(page, perPage, taskType, taskStatus) { return `${page}_${perPage}_${taskType || ''}_${taskStatus || ''}`; } get(page, perPage, taskType, taskStatus) { const key = this.getKey(page, perPage, taskType, taskStatus); const item = this.cache.get(key); if (!item) return null; if (Date.now() - item.timestamp > this.ttl) { this.cache.delete(key); return null; } return item.data; } set(page, perPage, taskType, taskStatus, data) { const key = this.getKey(page, perPage, taskType, taskStatus); this.cache.set(key, { data, timestamp: Date.now() }); } clear() { this.cache.clear(); } } const taskListCache = new TaskListCache(); ``` 4. **状态管理** ```javascript // 使用Vuex或类似状态管理 const parseTaskStore = { state: { taskList: [], currentTask: null, loading: false, error: null }, mutations: { SET_TASK_LIST(state, tasks) { state.taskList = tasks; }, SET_CURRENT_TASK(state, task) { state.currentTask = task; }, SET_LOADING(state, loading) { state.loading = loading; }, SET_ERROR(state, error) { state.error = error; } }, actions: { async loadTaskList({ commit }, { page, perPage, taskType, taskStatus }) { commit('SET_LOADING', true); commit('SET_ERROR', null); try { const data = await parseTaskAPI.getTaskList(page, perPage, taskType, taskStatus); commit('SET_TASK_LIST', data.tasks); return data; } catch (error) { commit('SET_ERROR', error.message); throw error; } finally { commit('SET_LOADING', false); } } } }; ``` ### 📱 响应式设计 ```css /* 移动端适配 */ @media (max-width: 768px) { .parse-task-manager { padding: 10px; } .el-table { font-size: 12px; } .el-table-column { min-width: 80px; } .create-task-section, .task-list-section { padding: 15px; margin-bottom: 20px; } } /* 大屏优化 */ @media (min-width: 1200px) { .parse-task-manager { max-width: 1200px; margin: 0 auto; } } ``` ### 🔍 调试工具 ```javascript // 开发环境调试工具 if (process.env.NODE_ENV === 'development') { window.parseTaskDebug = { // 显示API调用日志 enableAPILogging() { const originalRequest = parseTaskAPI.request; parseTaskAPI.request = function(...args) { console.group(`API调用: ${args[0]}`); console.log('参数:', args[1]); console.time('请求耗时'); return originalRequest.apply(this, args) .then(result => { console.log('响应:', result); console.timeEnd('请求耗时'); console.groupEnd(); return result; }) .catch(error => { console.error('错误:', error); console.timeEnd('请求耗时'); console.groupEnd(); throw error; }); }; }, // 模拟API响应 mockAPI(endpoint, response) { const originalRequest = parseTaskAPI.request; parseTaskAPI.request = function(url, options) { if (url.includes(endpoint)) { console.log(`Mock API: ${endpoint}`, response); return Promise.resolve(response); } return originalRequest.apply(this, arguments); }; } }; } ``` --- ## 📞 技术支持 如有任何问题,请联系: - **后端开发团队**: backend@company.com - **API文档维护**: api-docs@company.com - **技术支持**: tech-support@company.com --- > **文档更新记录** > - v1.0 (2025-01-18): 初始版本,包含5个解析任务管理接口的完整说明 > - 下次更新预计: 根据接口变更情况更新