add_webpage_talent_api_docs.md 17 KB

网页人才信息添加API使用说明手册

API概述

/add-webpage-talent 接口用于批量添加网页提取的人才信息到系统中。该接口能够将网页内容保存到MinIO存储,并为每个人才创建对应的业务卡片记录。


基本信息

项目
接口路径 /api/data-parse/add-webpage-talent
请求方法 POST
Content-Type application/json
认证方式 根据系统配置

输入参数

请求体结构

{
  "talent_list": [
    {
      "name_zh": "张三",
      "name_en": "Zhang San",
      "title_zh": "总经理",
      "title_en": "General Manager",
      "hotel_zh": "北京万豪酒店",
      "hotel_en": "Beijing Marriott Hotel",
      "brand_group": "万豪",
      "mobile": "13800138000",
      "email": "zhangsan@example.com",
      "phone": "010-12345678",
      "address_zh": "北京市朝阳区XXX路123号",
      "address_en": "123 XXX Road, Chaoyang District, Beijing",
      "postal_code_zh": "100000",
      "postal_code_en": "100000",
      "brand_zh": "万豪",
      "brand_en": "Marriott",
      "affiliation_zh": "万豪国际集团",
      "affiliation_en": "Marriott International",
      "birthday": "1980-01-01",
      "age": 44,
      "native_place": "北京市",
      "residence": "北京市朝阳区"
    }
  ],
  "web_md": "# 酒店任命公告\n\n## 人事变动\n\n1. **张三** 被任命为北京万豪酒店总经理...\n\n更多内容..."
}

参数详细说明

talent_list (必填)

  • 类型: Array<Object>
  • 描述: 人才信息列表,每个对象包含一个人才的详细信息
  • 限制: 非空数组

talent_list[].name_zh (必填)

  • 类型: String
  • 描述: 中文姓名
  • 示例: "张三"

talent_list[].name_en (可选)

  • 类型: String
  • 描述: 英文姓名
  • 示例: "Zhang San"

talent_list[].title_zh (可选)

  • 类型: String
  • 描述: 中文职位
  • 示例: "总经理"

talent_list[].title_en (可选)

  • 类型: String
  • 描述: 英文职位
  • 示例: "General Manager"

talent_list[].hotel_zh (可选)

  • 类型: String
  • 描述: 酒店中文名称
  • 示例: "北京万豪酒店"

talent_list[].hotel_en (可选)

  • 类型: String
  • 描述: 酒店英文名称
  • 示例: "Beijing Marriott Hotel"

talent_list[].brand_group (可选)

  • 类型: String
  • 描述: 品牌组合
  • 示例: "万豪"

talent_list[].mobile (可选)

  • 类型: String
  • 描述: 手机号码,支持多个号码用逗号分隔
  • 示例: "13800138000,13900139000"

talent_list[].email (可选)

  • 类型: String
  • 描述: 电子邮箱
  • 示例: "zhangsan@example.com"

talent_list[].phone (可选)

  • 类型: String
  • 描述: 固定电话
  • 示例: "010-12345678"

talent_list[].address_zh (可选)

  • 类型: String
  • 描述: 中文地址
  • 示例: "北京市朝阳区XXX路123号"

talent_list[].address_en (可选)

  • 类型: String
  • 描述: 英文地址
  • 示例: "123 XXX Road, Chaoyang District, Beijing"

talent_list[].birthday (可选)

  • 类型: String
  • 描述: 生日,格式为YYYY-MM-DD
  • 示例: "1980-01-01"

talent_list[].age (可选)

  • 类型: Integer
  • 描述: 年龄
  • 示例: 44

web_md (必填)

  • 类型: String
  • 描述: 网页的markdown格式文本内容,将被保存到MinIO存储
  • 限制: 非空字符串

输出参数

响应结构

成功响应 (所有记录处理成功)

{
  "code": 200,
  "success": true,
  "message": "所有3条人才记录处理成功",
  "data": {
    "total_count": 3,
    "success_count": 3,
    "failed_count": 0,
    "success_records": [
      {
        "index": 1,
        "data": {
          "id": 123,
          "name_zh": "张三",
          "name_en": "Zhang San",
          "title_zh": "总经理",
          "title_en": "General Manager",
          "hotel_zh": "北京万豪酒店",
          "hotel_en": "Beijing Marriott Hotel",
          "mobile": "13800138000",
          "email": "zhangsan@example.com",
          "brand_group": "万豪",
          "origin_source": {
            "type": "webpage_talent",
            "minio_path": "webpage_talent/webpage_talent_20240101_12345678.md",
            "source_date": "2024-01-01 12:00:00",
            "talent_data": {...},
            "web_md_content": "# 酒店任命公告..."
          },
          "created_at": "2024-01-01 12:00:00",
          "updated_at": "2024-01-01 12:00:00",
          "status": "active"
        },
        "message": "名片信息保存成功。未发现重复记录"
      }
    ],
    "failed_records": [],
    "minio_md_path": "webpage_talent/webpage_talent_20240101_12345678.md"
  }
}

部分成功响应

{
  "code": 206,
  "success": true,
  "message": "部分处理成功:2/3条记录成功",
  "data": {
    "total_count": 3,
    "success_count": 2,
    "failed_count": 1,
    "success_records": [...],
    "failed_records": [
      {
        "index": 3,
        "data": {
          "name_zh": "",
          "title_zh": "经理"
        },
        "error": "第3个记录缺少name_zh字段"
      }
    ],
    "minio_md_path": "webpage_talent/webpage_talent_20240101_12345678.md"
  }
}

错误响应

{
  "code": 400,
  "success": false,
  "message": "talent_list参数必须是非空数组",
  "data": null
}

响应字段说明

通用字段

  • code: HTTP状态码
  • success: 操作是否成功
  • message: 响应消息
  • data: 响应数据

成功响应数据字段

  • total_count: 总记录数
  • success_count: 成功处理的记录数
  • failed_count: 失败记录数
  • success_records: 成功记录详情列表
  • failed_records: 失败记录详情列表
  • minio_md_path: 网页内容在MinIO中的存储路径

返回状态码

状态码 说明 场景
200 成功 所有记录处理成功
206 部分成功 部分记录处理成功
400 请求参数错误 参数格式不正确或缺少必填参数
500 服务器内部错误 系统异常或数据库错误

前端代码示例

JavaScript (原生)

// 发送请求函数
async function addWebpageTalent(talentList, webMd) {
    const url = '/api/data-parse/add-webpage-talent';
    
    const requestBody = {
        talent_list: talentList,
        web_md: webMd
    };
    
    try {
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                // 如果需要认证,添加相应的头部
                // 'Authorization': 'Bearer your-token'
            },
            body: JSON.stringify(requestBody)
        });
        
        const result = await response.json();
        
        if (result.success) {
            console.log('处理成功:', result.message);
            console.log('处理详情:', result.data);
            
            // 处理成功记录
            if (result.data.success_records.length > 0) {
                console.log(`成功处理 ${result.data.success_count} 条记录`);
                result.data.success_records.forEach((record, index) => {
                    console.log(`记录 ${record.index}: ${record.data.name_zh} - ${record.message}`);
                });
            }
            
            // 处理失败记录
            if (result.data.failed_records.length > 0) {
                console.log(`失败 ${result.data.failed_count} 条记录`);
                result.data.failed_records.forEach((record, index) => {
                    console.error(`记录 ${record.index}: ${record.error}`);
                });
            }
            
            return result;
        } else {
            console.error('处理失败:', result.message);
            throw new Error(result.message);
        }
    } catch (error) {
        console.error('请求失败:', error);
        throw error;
    }
}

// 使用示例
const talentData = [
    {
        name_zh: "张三",
        name_en: "Zhang San",
        title_zh: "总经理",
        title_en: "General Manager",
        hotel_zh: "北京万豪酒店",
        hotel_en: "Beijing Marriott Hotel",
        brand_group: "万豪",
        mobile: "13800138000",
        email: "zhangsan@example.com"
    },
    {
        name_zh: "李四",
        name_en: "Li Si",
        title_zh: "副总经理",
        title_en: "Deputy General Manager",
        hotel_zh: "上海希尔顿酒店",
        hotel_en: "Shanghai Hilton Hotel",
        brand_group: "希尔顿",
        mobile: "13900139000",
        email: "lisi@example.com"
    }
];

const webContent = `
# 酒店人事任命公告

## 重要人事变动

1. **张三**被任命为北京万豪酒店总经理
   - 手机:13800138000
   - 邮箱:zhangsan@example.com

2. **李四**被任命为上海希尔顿酒店副总经理
   - 手机:13900139000
   - 邮箱:lisi@example.com
`;

// 调用函数
addWebpageTalent(talentData, webContent)
    .then(result => {
        console.log('操作完成:', result);
    })
    .catch(error => {
        console.error('操作失败:', error);
    });

jQuery

function addWebpageTalent(talentList, webMd) {
    return $.ajax({
        url: '/api/data-parse/add-webpage-talent',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({
            talent_list: talentList,
            web_md: webMd
        }),
        success: function(result) {
            if (result.success) {
                console.log('处理成功:', result.message);
                
                // 显示处理结果
                if (result.data.success_count > 0) {
                    alert(`成功处理 ${result.data.success_count} 条记录`);
                }
                
                if (result.data.failed_count > 0) {
                    console.warn(`失败 ${result.data.failed_count} 条记录`);
                    result.data.failed_records.forEach(record => {
                        console.error(`记录 ${record.index}: ${record.error}`);
                    });
                }
            } else {
                alert('处理失败: ' + result.message);
            }
        },
        error: function(xhr, status, error) {
            console.error('请求失败:', error);
            alert('请求失败: ' + error);
        }
    });
}

// 使用示例
const talentData = [
    {
        name_zh: "张三",
        title_zh: "总经理",
        hotel_zh: "北京万豪酒店",
        mobile: "13800138000"
    }
];

const webContent = "# 人事任命公告\n\n张三被任命为总经理...";

addWebpageTalent(talentData, webContent);

Vue.js

<template>
  <div>
    <h3>添加网页人才信息</h3>
    
    <!-- 人才信息表单 -->
    <div v-for="(talent, index) in talentList" :key="index" class="talent-form">
      <h4>人才 {{ index + 1 }}</h4>
      <div class="form-group">
        <label>中文姓名 (必填):</label>
        <input v-model="talent.name_zh" type="text" required>
      </div>
      <div class="form-group">
        <label>英文姓名:</label>
        <input v-model="talent.name_en" type="text">
      </div>
      <div class="form-group">
        <label>中文职位:</label>
        <input v-model="talent.title_zh" type="text">
      </div>
      <div class="form-group">
        <label>酒店名称:</label>
        <input v-model="talent.hotel_zh" type="text">
      </div>
      <div class="form-group">
        <label>手机号码:</label>
        <input v-model="talent.mobile" type="text">
      </div>
      <div class="form-group">
        <label>电子邮箱:</label>
        <input v-model="talent.email" type="email">
      </div>
    </div>
    
    <!-- 网页内容 -->
    <div class="form-group">
      <label>网页内容 (Markdown格式):</label>
      <textarea v-model="webMd" rows="10" cols="50" required></textarea>
    </div>
    
    <!-- 操作按钮 -->
    <div class="actions">
      <button @click="addTalent">添加人才</button>
      <button @click="submitData" :disabled="loading">
        {{ loading ? '处理中...' : '提交数据' }}
      </button>
    </div>
    
    <!-- 结果显示 -->
    <div v-if="result" class="result">
      <h4>处理结果</h4>
      <p :class="result.success ? 'success' : 'error'">{{ result.message }}</p>
      
      <div v-if="result.data">
        <p>总记录数: {{ result.data.total_count }}</p>
        <p>成功: {{ result.data.success_count }}</p>
        <p>失败: {{ result.data.failed_count }}</p>
        
        <div v-if="result.data.failed_records.length > 0">
          <h5>失败记录:</h5>
          <ul>
            <li v-for="record in result.data.failed_records" :key="record.index">
              记录 {{ record.index }}: {{ record.error }}
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'AddWebpageTalent',
  data() {
    return {
      talentList: [
        {
          name_zh: '',
          name_en: '',
          title_zh: '',
          title_en: '',
          hotel_zh: '',
          hotel_en: '',
          brand_group: '',
          mobile: '',
          email: '',
          phone: '',
          address_zh: '',
          address_en: ''
        }
      ],
      webMd: '',
      loading: false,
      result: null
    };
  },
  methods: {
    addTalent() {
      this.talentList.push({
        name_zh: '',
        name_en: '',
        title_zh: '',
        title_en: '',
        hotel_zh: '',
        hotel_en: '',
        brand_group: '',
        mobile: '',
        email: '',
        phone: '',
        address_zh: '',
        address_en: ''
      });
    },
    
    async submitData() {
      if (!this.validateData()) {
        return;
      }
      
      this.loading = true;
      this.result = null;
      
      try {
        const response = await fetch('/api/data-parse/add-webpage-talent', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            talent_list: this.talentList,
            web_md: this.webMd
          })
        });
        
        const result = await response.json();
        this.result = result;
        
        if (result.success) {
          this.$message.success(result.message);
        } else {
          this.$message.error(result.message);
        }
      } catch (error) {
        this.result = {
          success: false,
          message: '请求失败: ' + error.message
        };
        this.$message.error('请求失败: ' + error.message);
      } finally {
        this.loading = false;
      }
    },
    
    validateData() {
      // 验证必填字段
      for (let i = 0; i < this.talentList.length; i++) {
        if (!this.talentList[i].name_zh.trim()) {
          this.$message.error(`第 ${i + 1} 个人才的中文姓名不能为空`);
          return false;
        }
      }
      
      if (!this.webMd.trim()) {
        this.$message.error('网页内容不能为空');
        return false;
      }
      
      return true;
    }
  }
};
</script>

<style scoped>
.talent-form {
  border: 1px solid #ddd;
  padding: 15px;
  margin: 10px 0;
  border-radius: 5px;
}

.form-group {
  margin: 10px 0;
}

.form-group label {
  display: inline-block;
  width: 120px;
  font-weight: bold;
}

.form-group input,
.form-group textarea {
  width: 300px;
  padding: 5px;
  border: 1px solid #ccc;
  border-radius: 3px;
}

.actions {
  margin: 20px 0;
}

.actions button {
  margin-right: 10px;
  padding: 10px 20px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

.actions button:disabled {
  background: #6c757d;
  cursor: not-allowed;
}

.result {
  margin: 20px 0;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

.success {
  color: #28a745;
}

.error {
  color: #dc3545;
}
</style>

错误处理

常见错误及解决方案

1. 参数验证错误

错误: talent_list参数必须是非空数组 解决: 确保talent_list是一个非空数组

2. 缺少必填字段

错误: 第X个记录缺少name_zh字段 解决: 确保每个人才记录都包含name_zh字段

3. MinIO上传失败

错误: 上传网页内容到MinIO失败 解决: 检查MinIO服务状态和配置

4. 数据库错误

错误: 数据库操作失败 解决: 检查数据库连接和表结构


注意事项

  1. 数据完整性: 确保talent_list中每个对象都包含name_zh字段
  2. 内容大小: web_md内容不应过大,建议控制在合理范围内
  3. 并发处理: 该接口支持批量处理,但建议控制单次请求的记录数量
  4. 重复检查: 系统会自动检查重复记录并相应处理
  5. 存储路径: 网页内容会自动保存到MinIO的webpage_talent/目录下
  6. 数据溯源: origin_source字段保存了完整的数据来源信息,便于后续追溯

版本信息

  • API版本: v1.0
  • 文档版本: 1.0.0
  • 创建日期: 2024年
  • 最后更新: 2024年

联系支持

如果在使用过程中遇到问题,请联系技术支持团队。