Explorar el Código

新增人才标签增删改查接口。制作人才标签API文档。

maxiaolong hace 1 semana
padre
commit
45e9e5c355
Se han modificado 3 ficheros con 808 adiciones y 34 borrados
  1. 171 1
      app/api/data_parse/routes.py
  2. 314 33
      app/core/data_parse/parse.py
  3. 323 0
      talent_tag_api_documentation.md

+ 171 - 1
app/api/data_parse/routes.py

@@ -1,6 +1,6 @@
 from flask import jsonify, request, make_response, Blueprint, current_app, send_file
 from app.api.data_parse import bp
-from app.core.data_parse.parse import parse_data, process_business_card, update_business_card, get_business_cards, update_business_card_status, get_business_card_image_from_minio
+from app.core.data_parse.parse import parse_data, process_business_card, update_business_card, get_business_cards, update_business_card_status, create_talent_tag, get_talent_tag_list, update_talent_tag, delete_talent_tag
 from app.config.config import DevelopmentConfig, ProductionConfig
 import logging
 import boto3
@@ -248,3 +248,173 @@ def get_business_card_image(image_path):
         if 'data' in locals():
             data.close()
 
+# 创建人才标签接口
+@bp.route('/create-talent-tag', methods=['POST'])
+def create_talent_tag_route():
+    """
+    创建人才标签的API接口
+    
+    请求参数:
+        - JSON格式,包含以下字段:
+            - name: 标签名称
+            - category: 标签分类
+            - description: 标签描述
+            - status: 启用状态,默认为'active'
+        
+    返回:
+        - JSON: 包含创建结果和标签信息
+    """
+    try:
+        # 获取请求数据
+        data = request.get_json()
+        
+        if not data:
+            return jsonify({
+                'success': False,
+                'message': '请求数据为空',
+                'data': None
+            }), 400
+        
+        # 验证必要字段
+        if 'name' not in data or not data['name']:
+            return jsonify({
+                'success': False,
+                'message': '标签名称不能为空',
+                'data': None
+            }), 400
+        
+        # 处理分类字段,如果未提供则设置默认值
+        if 'category' not in data or not data['category']:
+            data['category'] = '未分类'
+            
+        # 调用业务逻辑函数处理创建
+        result = create_talent_tag(data)
+        
+        # 根据处理结果设置HTTP状态码
+        status_code = 200 if result['success'] else 500
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        logger.error(f"创建人才标签失败: {str(e)}")
+        return jsonify({
+            'success': False,
+            'message': f'创建人才标签失败: {str(e)}',
+            'data': None
+        }), 500
+
+# 获取人才标签列表接口
+@bp.route('/get-talent-tag-list', methods=['GET'])
+def get_talent_tag_list_route():
+    """
+    获取人才标签列表的API接口
+    
+    返回:
+        - JSON: 包含人才标签列表和处理状态
+    """
+    try:
+        # 调用业务逻辑函数获取人才标签列表
+        result = get_talent_tag_list()
+        
+        # 根据处理结果设置HTTP状态码
+        status_code = 200 if result['success'] else 500
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        logger.error(f"获取人才标签列表失败: {str(e)}")
+        return jsonify({
+            'success': False,
+            'message': f'获取人才标签列表失败: {str(e)}',
+            'data': []
+        }), 500
+
+# 更新人才标签接口
+@bp.route('/update-talent-tag/<int:tag_id>', methods=['PUT'])
+def update_talent_tag_route(tag_id):
+    """
+    更新人才标签的API接口
+    
+    路径参数:
+        - tag_id: 标签节点ID
+    
+    请求参数:
+        - JSON格式,可能包含以下字段:
+            - name: 标签名称
+            - category: 标签分类
+            - description: 标签描述
+            - status: 启用状态
+        
+    返回:
+        - JSON: 包含更新结果和标签信息
+    """
+    try:
+        # 获取请求数据
+        data = request.get_json()
+        
+        if not data:
+            return jsonify({
+                'success': False,
+                'message': '请求数据为空',
+                'data': None
+            }), 400
+        
+        # 调用业务逻辑函数处理更新
+        result = update_talent_tag(tag_id, data)
+        
+        # 根据处理结果设置HTTP状态码
+        if not result['success']:
+            if result['code'] == 404:
+                status_code = 404
+            elif result['code'] == 400:
+                status_code = 400
+            else:
+                status_code = 500
+        else:
+            status_code = 200
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        logger.error(f"更新人才标签失败: {str(e)}")
+        return jsonify({
+            'success': False,
+            'message': f'更新人才标签失败: {str(e)}',
+            'data': None
+        }), 500
+
+# 删除人才标签接口
+@bp.route('/delete-talent-tag/<int:tag_id>', methods=['DELETE'])
+def delete_talent_tag_route(tag_id):
+    """
+    删除人才标签的API接口
+    
+    路径参数:
+        - tag_id: 标签节点ID
+        
+    返回:
+        - JSON: 包含删除结果和被删除的标签信息
+    """
+    try:
+        # 调用业务逻辑函数执行删除
+        result = delete_talent_tag(tag_id)
+        
+        # 根据处理结果设置HTTP状态码
+        if not result['success']:
+            if result['code'] == 404:
+                status_code = 404
+            else:
+                status_code = 500
+        else:
+            status_code = 200
+        
+        return jsonify(result), status_code
+        
+    except Exception as e:
+        logger.error(f"删除人才标签失败: {str(e)}")
+        return jsonify({
+            'success': False,
+            'message': f'删除人才标签失败: {str(e)}',
+            'data': None
+        }), 500
+

+ 314 - 33
app/core/data_parse/parse.py

@@ -907,49 +907,330 @@ def update_business_card_status(card_id, status):
             'data': None
         }
 
-'''
-def get_business_card_image_from_minio(image_path):
+def create_talent_tag(tag_data):
     """
-    从MinIO获取名片图片
+    创建人才标签节点
     
     Args:
-        image_path (str): MinIO中的图片路径
+        tag_data: 包含标签信息的字典,包括:
+            - name: 标签名称
+            - category: 标签分类
+            - description: 标签描述
+            - status: 启用状态
+    
+    Returns:
+        dict: 操作结果字典
+    """
+    try:
+        from app.services.neo4j_driver import neo4j_driver
         
+        # 准备节点属性
+        tag_properties = {
+            'name': tag_data.get('name'),
+            'category': tag_data.get('category', '未分类'),
+            'describe': tag_data.get('description', ''),  # 使用describe与现有系统保持一致
+            'status': tag_data.get('status', 'active'),
+            'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+        }
+        
+        # 生成标签的英文名(可选)
+        from app.core.graph.graph_operations import create_or_get_node
+        
+        # 如果提供了名称,尝试获取英文翻译
+        if 'name' in tag_data and tag_data['name']:
+            try:
+                from app.api.data_interface.routes import translate_and_parse
+                en_name = translate_and_parse(tag_data['name'])
+                tag_properties['en_name'] = en_name[0] if en_name and isinstance(en_name, list) else ''
+            except Exception as e:
+                logging.warning(f"获取标签英文名失败: {str(e)}")
+                tag_properties['en_name'] = ''
+                
+        # 创建节点
+        node_id = create_or_get_node('data_label', **tag_properties)
+        
+        if node_id:
+            return {
+                'code': 200,
+                'success': True,
+                'message': '人才标签创建成功',
+                'data': {
+                    'id': node_id,
+                    **tag_properties
+                }
+            }
+        else:
+            return {
+                'code': 500,
+                'success': False,
+                'message': '人才标签创建失败',
+                'data': None
+            }
+            
+    except Exception as e:
+        logging.error(f"创建人才标签失败: {str(e)}", exc_info=True)
+        return {
+            'code': 500,
+            'success': False,
+            'message': f'创建人才标签失败: {str(e)}',
+            'data': None
+        }
+
+def get_talent_tag_list():
+    """
+    从Neo4j图数据库获取人才标签列表
+    
     Returns:
-        tuple: (success, file_data, content_type, status_code)
-            - success: 是否成功获取图片
-            - file_data: 图片二进制数据
-            - content_type: 图片内容类型
-            - status_code: HTTP状态码
+        dict: 包含操作结果和标签列表的字典
     """
-    response = None
     try:
-        minio_client = get_minio_client()
+        from app.services.neo4j_driver import neo4j_driver
         
-        if not minio_client:
-            logging.error("MinIO客户端初始化失败")
-            return False, None, None, 500
+        # 构建Cypher查询语句,获取分类为talent的标签
+        query = """
+        MATCH (n:data_label)
+        WHERE n.category CONTAINS 'talent' OR n.category CONTAINS '人才'
+        RETURN id(n) as id, n.name as name, n.en_name as en_name, 
+               n.category as category, n.describe as description, 
+               n.status as status, n.time as time
+        ORDER BY n.time DESC
+        """
         
-        # 获取文件
-        try:
-            response = minio_client.get_object(
-                Bucket=minio_bucket,
-                Key=image_path
-            )
-            file_data = response.read()
-            content_type = response.content_type
+        # 执行查询
+        tags = []
+        with neo4j_driver.get_session() as session:
+            result = session.run(query)
             
-            return True, file_data, content_type, 200
+            # 处理查询结果
+            for record in result:
+                tag = {
+                    'id': record['id'],
+                    'name': record['name'],
+                    'en_name': record['en_name'],
+                    'category': record['category'],
+                    'description': record['description'],
+                    'status': record['status'],
+                    'time': record['time']
+                }
+                tags.append(tag)
+        
+        return {
+            'code': 200,
+            'success': True,
+            'message': '获取人才标签列表成功',
+            'data': tags
+        }
+        
+    except Exception as e:
+        error_msg = f"获取人才标签列表失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': []
+        }
+
+def update_talent_tag(tag_id, tag_data):
+    """
+    更新人才标签节点属性
+    
+    Args:
+        tag_id: 标签节点ID
+        tag_data: 包含更新信息的字典,可能包括:
+            - name: 标签名称
+            - category: 标签分类
+            - description: 标签描述
+            - status: 启用状态
+    
+    Returns:
+        dict: 操作结果字典
+    """
+    try:
+        from app.services.neo4j_driver import neo4j_driver
+        
+        # 准备要更新的属性
+        update_properties = {}
+        
+        # 检查并添加需要更新的属性
+        if 'name' in tag_data and tag_data['name']:
+            update_properties['name'] = tag_data['name']
             
-        except Exception as e:
-            logging.error(f"MinIO获取图片失败: {str(e)}")
-            return False, None, None, 404
+            # 如果名称更新了,尝试更新英文名称
+            try:
+                from app.api.data_interface.routes import translate_and_parse
+                en_name = translate_and_parse(tag_data['name'])
+                update_properties['en_name'] = en_name[0] if en_name and isinstance(en_name, list) else ''
+            except Exception as e:
+                logging.warning(f"更新标签英文名失败: {str(e)}")
+        
+        if 'category' in tag_data and tag_data['category']:
+            update_properties['category'] = tag_data['category']
+            
+        if 'description' in tag_data:
+            update_properties['describe'] = tag_data['description']
+            
+        if 'status' in tag_data:
+            update_properties['status'] = tag_data['status']
+            
+        # 添加更新时间
+        update_properties['time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
         
+        # 如果没有可更新的属性,返回错误
+        if not update_properties:
+            return {
+                'code': 400,
+                'success': False,
+                'message': '未提供任何可更新的属性',
+                'data': None
+            }
+        
+        # 构建更新的Cypher查询
+        set_clauses = []
+        params = {'nodeId': tag_id}
+        
+        for key, value in update_properties.items():
+            param_name = f"param_{key}"
+            set_clauses.append(f"n.{key} = ${param_name}")
+            params[param_name] = value
+            
+        set_clause = ", ".join(set_clauses)
+        
+        query = f"""
+        MATCH (n:data_label)
+        WHERE id(n) = $nodeId
+        SET {set_clause}
+        RETURN id(n) as id, n.name as name, n.en_name as en_name, 
+               n.category as category, n.describe as description, 
+               n.status as status, n.time as time
+        """
+        
+        # 执行更新查询
+        with neo4j_driver.get_session() as session:
+            result = session.run(query, **params)
+            record = result.single()
+            
+            if not record:
+                return {
+                    'code': 404,
+                    'success': False,
+                    'message': f'未找到ID为{tag_id}的标签',
+                    'data': None
+                }
+                
+            # 提取更新后的标签信息
+            updated_tag = {
+                'id': record['id'],
+                'name': record['name'],
+                'en_name': record['en_name'],
+                'category': record['category'],
+                'description': record['description'],
+                'status': record['status'],
+                'time': record['time']
+            }
+            
+            return {
+                'code': 200,
+                'success': True,
+                'message': '人才标签更新成功',
+                'data': updated_tag
+            }
+            
     except Exception as e:
-        logging.error(f"获取图片过程中发生错误: {str(e)}")
-        return False, None, None, 500
-    finally:
-        # 关闭响应连接(如果存在)
-        if response and hasattr(response.get('Body', None), 'close'):
-            response['Body'].close()
-'''            
+        error_msg = f"更新人才标签失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }
+
+def delete_talent_tag(tag_id):
+    """
+    删除人才标签节点及其相关关系
+    
+    Args:
+        tag_id: 标签节点ID
+    
+    Returns:
+        dict: 操作结果字典
+    """
+    try:
+        from app.services.neo4j_driver import neo4j_driver
+        
+        # 首先获取要删除的标签信息,以便在成功后返回
+        get_query = """
+        MATCH (n:data_label)
+        WHERE id(n) = $nodeId
+        RETURN id(n) as id, n.name as name, n.en_name as en_name, 
+               n.category as category, n.describe as description, 
+               n.status as status, n.time as time
+        """
+        
+        # 构建删除节点和关系的Cypher查询
+        delete_query = """
+        MATCH (n:data_label)
+        WHERE id(n) = $nodeId
+        OPTIONAL MATCH (n)-[r]-()
+        DELETE r, n
+        RETURN count(n) AS deleted
+        """
+        
+        # 执行查询
+        tag_info = None
+        with neo4j_driver.get_session() as session:
+            # 先获取标签信息
+            result = session.run(get_query, nodeId=tag_id)
+            record = result.single()
+            
+            if not record:
+                return {
+                    'code': 404,
+                    'success': False,
+                    'message': f'未找到ID为{tag_id}的标签',
+                    'data': None
+                }
+                
+            # 保存标签信息用于返回
+            tag_info = {
+                'id': record['id'],
+                'name': record['name'],
+                'en_name': record['en_name'],
+                'category': record['category'],
+                'description': record['description'],
+                'status': record['status'],
+                'time': record['time']
+            }
+            
+            # 执行删除操作
+            delete_result = session.run(delete_query, nodeId=tag_id)
+            deleted = delete_result.single()['deleted']
+            
+            if deleted > 0:
+                return {
+                    'code': 200,
+                    'success': True,
+                    'message': '人才标签删除成功',
+                    'data': tag_info
+                }
+            else:
+                return {
+                    'code': 404,
+                    'success': False,
+                    'message': f'未能删除ID为{tag_id}的标签',
+                    'data': None
+                }
+            
+    except Exception as e:
+        error_msg = f"删除人才标签失败: {str(e)}"
+        logging.error(error_msg, exc_info=True)
+        
+        return {
+            'code': 500,
+            'success': False,
+            'message': error_msg,
+            'data': None
+        }

+ 323 - 0
talent_tag_api_documentation.md

@@ -0,0 +1,323 @@
+# 人才标签 API 接口文档
+
+本文档详细说明了人才标签管理的四个 API 接口,包括创建、查询、更新和删除人才标签的操作。
+
+## 目录
+
+- [创建人才标签](#创建人才标签)
+- [获取人才标签列表](#获取人才标签列表)
+- [更新人才标签](#更新人才标签)
+- [删除人才标签](#删除人才标签)
+
+## 创建人才标签
+
+创建新的人才标签节点到 Neo4j 图数据库中。
+
+### 请求信息
+
+- **URL:** `/api/parse/create-talent-tag`
+- **方法:** `POST`
+- **Content-Type:** `application/json`
+
+### 请求参数
+
+| 参数名      | 类型   | 必填 | 描述                               |
+|------------|--------|------|-----------------------------------|
+| name       | String | 是   | 标签名称                           |
+| category   | String | 否   | 标签分类,默认为"未分类"           |
+| description| String | 否   | 标签描述                           |
+| status     | String | 否   | 标签状态,默认为"active"           |
+
+### 请求示例
+
+```json
+{
+  "name": "Java开发",
+  "category": "技术能力/人才",
+  "description": "熟练掌握Java编程语言和相关框架",
+  "status": "active"
+}
+```
+
+### 响应参数
+
+| 参数名      | 类型    | 描述                               |
+|------------|---------|-----------------------------------|
+| success    | Boolean | 操作是否成功                       |
+| message    | String  | 操作结果描述                       |
+| code       | Integer | 状态码                             |
+| data       | Object  | 创建的标签信息                     |
+
+### 响应示例 - 成功
+
+```json
+{
+  "success": true,
+  "message": "人才标签创建成功",
+  "code": 200,
+  "data": {
+    "id": 12345,
+    "name": "Java开发",
+    "en_name": "Java Development",
+    "category": "技术能力/人才",
+    "description": "熟练掌握Java编程语言和相关框架",
+    "status": "active",
+    "time": "2023-07-20 14:30:45"
+  }
+}
+```
+
+### 响应示例 - 失败
+
+```json
+{
+  "success": false,
+  "message": "标签名称不能为空",
+  "code": 400,
+  "data": null
+}
+```
+
+### 状态码
+
+| 状态码 | 描述                 |
+|--------|---------------------|
+| 200    | 请求成功             |
+| 400    | 请求参数错误         |
+| 500    | 服务器内部错误       |
+
+---
+
+## 获取人才标签列表
+
+从 Neo4j 图数据库获取人才标签列表,包括所有分类包含"talent"或"人才"的标签。
+
+### 请求信息
+
+- **URL:** `/api/parse/get-talent-tag-list`
+- **方法:** `GET`
+
+### 请求参数
+
+无
+
+### 响应参数
+
+| 参数名      | 类型    | 描述                               |
+|------------|---------|-----------------------------------|
+| success    | Boolean | 操作是否成功                       |
+| message    | String  | 操作结果描述                       |
+| code       | Integer | 状态码                             |
+| data       | Array   | 人才标签列表                       |
+
+### 响应示例 - 成功
+
+```json
+{
+  "success": true,
+  "message": "获取人才标签列表成功",
+  "code": 200,
+  "data": [
+    {
+      "id": 12345,
+      "name": "Java开发",
+      "en_name": "Java Development",
+      "category": "技术能力/人才",
+      "description": "熟练掌握Java编程语言和相关框架",
+      "status": "active",
+      "time": "2023-07-20 14:30:45"
+    },
+    {
+      "id": 12346,
+      "name": "Python开发",
+      "en_name": "Python Development",
+      "category": "技术能力/人才",
+      "description": "熟练掌握Python编程语言和相关框架",
+      "status": "active",
+      "time": "2023-07-19 10:15:22"
+    }
+  ]
+}
+```
+
+### 响应示例 - 失败
+
+```json
+{
+  "success": false,
+  "message": "获取人才标签列表失败: 数据库连接错误",
+  "code": 500,
+  "data": []
+}
+```
+
+### 状态码
+
+| 状态码 | 描述                 |
+|--------|---------------------|
+| 200    | 请求成功             |
+| 500    | 服务器内部错误       |
+
+---
+
+## 更新人才标签
+
+更新已有的人才标签节点属性。
+
+### 请求信息
+
+- **URL:** `/api/parse/update-talent-tag/{tag_id}`
+- **方法:** `PUT`
+- **Content-Type:** `application/json`
+
+### 路径参数
+
+| 参数名 | 类型    | 描述           |
+|--------|---------|---------------|
+| tag_id | Integer | 要更新的标签ID |
+
+### 请求参数
+
+| 参数名      | 类型   | 必填 | 描述                               |
+|------------|--------|------|-----------------------------------|
+| name       | String | 否   | 标签名称                           |
+| category   | String | 否   | 标签分类                           |
+| description| String | 否   | 标签描述                           |
+| status     | String | 否   | 标签状态                           |
+
+注意:至少需要提供一个参数进行更新。
+
+### 请求示例
+
+```json
+{
+  "name": "高级Java开发",
+  "description": "精通Java编程语言和相关框架,有丰富的项目经验"
+}
+```
+
+### 响应参数
+
+| 参数名      | 类型    | 描述                               |
+|------------|---------|-----------------------------------|
+| success    | Boolean | 操作是否成功                       |
+| message    | String  | 操作结果描述                       |
+| code       | Integer | 状态码                             |
+| data       | Object  | 更新后的标签信息                   |
+
+### 响应示例 - 成功
+
+```json
+{
+  "success": true,
+  "message": "人才标签更新成功",
+  "code": 200,
+  "data": {
+    "id": 12345,
+    "name": "高级Java开发",
+    "en_name": "Senior Java Development",
+    "category": "技术能力/人才",
+    "description": "精通Java编程语言和相关框架,有丰富的项目经验",
+    "status": "active",
+    "time": "2023-07-21 09:45:30"
+  }
+}
+```
+
+### 响应示例 - 失败
+
+```json
+{
+  "success": false,
+  "message": "未找到ID为12345的标签",
+  "code": 404,
+  "data": null
+}
+```
+
+### 状态码
+
+| 状态码 | 描述                 |
+|--------|---------------------|
+| 200    | 请求成功             |
+| 400    | 请求参数错误         |
+| 404    | 标签不存在           |
+| 500    | 服务器内部错误       |
+
+---
+
+## 删除人才标签
+
+删除指定的人才标签节点及其关系。
+
+### 请求信息
+
+- **URL:** `/api/parse/delete-talent-tag/{tag_id}`
+- **方法:** `DELETE`
+
+### 路径参数
+
+| 参数名 | 类型    | 描述           |
+|--------|---------|---------------|
+| tag_id | Integer | 要删除的标签ID |
+
+### 请求参数
+
+无
+
+### 响应参数
+
+| 参数名      | 类型    | 描述                               |
+|------------|---------|-----------------------------------|
+| success    | Boolean | 操作是否成功                       |
+| message    | String  | 操作结果描述                       |
+| code       | Integer | 状态码                             |
+| data       | Object  | 被删除的标签信息                   |
+
+### 响应示例 - 成功
+
+```json
+{
+  "success": true,
+  "message": "人才标签删除成功",
+  "code": 200,
+  "data": {
+    "id": 12345,
+    "name": "高级Java开发",
+    "en_name": "Senior Java Development",
+    "category": "技术能力/人才",
+    "description": "精通Java编程语言和相关框架,有丰富的项目经验",
+    "status": "active",
+    "time": "2023-07-21 09:45:30"
+  }
+}
+```
+
+### 响应示例 - 失败
+
+```json
+{
+  "success": false,
+  "message": "未找到ID为12345的标签",
+  "code": 404,
+  "data": null
+}
+```
+
+### 状态码
+
+| 状态码 | 描述                 |
+|--------|---------------------|
+| 200    | 请求成功             |
+| 404    | 标签不存在           |
+| 500    | 服务器内部错误       |
+
+---
+
+## 开发注意事项
+
+1. 所有请求和响应的 Content-Type 均为 `application/json`。
+2. 创建标签时,name 字段为必填,其他字段可选。
+3. 更新标签时,至少需要提供一个要更新的属性。
+4. 删除标签时会同时删除该标签与其他节点之间的所有关系。
+5. 英文名称(en_name)会根据中文名称自动生成,无需手动提供。