# 解析任务管理类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
解析任务管理
创建新任务
选择文件
创建任务
任务列表
详情
执行
基本信息
任务名称: {{ currentTask.task_name }}
任务类型: {{ currentTask.task_type }}
任务状态: {{ currentTask.task_status }}
文件数量: {{ currentTask.collection_count }}
解析数量: {{ currentTask.parse_count }}
解析结果
{{ JSON.stringify(currentTask.parse_result, null, 2) }}
```
### 🔧 工具类封装
```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个解析任务管理接口的完整说明
> - 下次更新预计: 根据接口变更情况更新