from datetime import datetime from flask import Blueprint, current_app, request, jsonify from flask_jwt_extended import jwt_required import requests from sqlalchemy import func from app import db from app.models import Fst from app.utils.fst_tree import build_tree label_bp = Blueprint('label', __name__) def format_fst_item(fst_item): """将Fst对象转换为指定格式的字典""" # 从reserved_json中获取type,如果没有则默认为空字符串 item_type = "" if fst_item.reserved_json and "type" in fst_item.reserved_json: item_type = fst_item.reserved_json["type"] return { "date": fst_item.update_time.strftime('%Y-%m-%d'), # 格式化日期 "id": fst_item.id, "name": fst_item.name, "parentId": None if fst_item.parent_id==591 else fst_item.parent_id, # 注意这里是驼峰命名 "name_cn": fst_item.name_cn, "annotation":fst_item.annotation, "level":fst_item.level } @label_bp.route('/fst-tree', methods=['GET']) def get_fst_tree(): """获取所有FST数据并格式化为树形结构列表""" try: # 查询所有FST记录 all_fst = Fst.query.all() # 转换为指定格式 formatted_data = [format_fst_item(item) for item in all_fst] # 返回JSON响应 return jsonify({ "success": True, "data": formatted_data }) except Exception as e: return jsonify({ "success": False, "error": str(e) }), 500 @label_bp.route('/create-levelone', methods=['POST']) @jwt_required() def create_levelone(): # 获取请求数据 data = request.get_json() # 验证必要参数 required_fields = ['name', 'level', 'annotation'] for field in required_fields: if field not in data: return jsonify({'error': f'Missing required field: {field}'}), 400 # 验证层级是否为1 if data['level'] != 1: return jsonify({'error': 'Level must be 1 for first-level tags'}), 400 try: # 查询当前最大的id值 max_id_result = db.session.query(func.max(Fst.id)).first() max_id = max_id_result[0] if max_id_result[0] is not None else 0 # 新id为最大id + 1 new_id = max_id + 1 # 创建新的一级标签 new_tag = Fst( id=new_id, name=data['name'], level=data['level'], annotation=data['annotation'], parent_id=591, # 固定设置parent_id为591 update_time=datetime.now() # 设置更新时间 # 其他字段如name_cn、reserved_json、bag_sum如果有默认值可以不用指定 ) # 添加到数据库会话并提交 db.session.add(new_tag) db.session.commit() # print(f"新标签的ID: {new_tag.id}") # 返回创建成功的标签信息 return jsonify({ 'message': 'First-level tag created successfully', 'tag': { 'id': new_tag.id, 'name': new_tag.name, 'level': new_tag.level, 'annotation': new_tag.annotation, 'parent_id': new_tag.parent_id, 'update_time': new_tag.update_time.isoformat() } }), 201 except Exception as e: # 发生错误时回滚 db.session.rollback() return jsonify({'error': str(e)}), 500 @label_bp.route('/update-fst-annotation', methods=['POST']) @jwt_required() def update_fst_annotation(): # 获取请求数据 data = request.get_json() # 验证必要参数 required_fields = ['name', 'level', 'annotation'] for field in required_fields: if field not in data: return jsonify({'error': f'Missing required field: {field}'}), 400 try: # 根据name和level查询对应的记录 fst_record = Fst.query.filter_by( name=data['name'], level=data['level'] ).first() # 检查记录是否存在 if not fst_record: return jsonify({ 'error': f'No record found with name: {data["name"]} and level: {data["level"]}' }), 404 # 更新annotation字段和更新时间 fst_record.annotation = data['annotation'] fst_record.update_time = datetime.now() # 更新时间戳 # 提交修改 db.session.commit() # 返回更新成功的信息 return jsonify({ 'message': 'Annotation updated successfully', 'updated_record': { 'id': fst_record.id, 'name': fst_record.name, 'level': fst_record.level, 'annotation': fst_record.annotation, 'update_time': fst_record.update_time.isoformat() } }), 200 except Exception as e: # 发生错误时回滚 db.session.rollback() return jsonify({'error': str(e)}), 500 @label_bp.route('/add-fst', methods=['POST']) @jwt_required() def add_fst(): # 获取请求数据 data = request.get_json() # 验证必要参数 required_fields = ['name', 'level', 'parentName', 'annotation'] for field in required_fields: if field not in data: return jsonify({'error': f'Missing required field: {field}'}), 400 try: # 根据parentName查询父标签的记录,获取parent_id parent_record = Fst.query.filter_by(name=data['parentName']).first() # 检查父标签是否存在 if not parent_record: return jsonify({ 'error': f'Parent tag not found with name: {data["parentName"]}' }), 404 # 查询当前最大的id值 max_id_result = db.session.query(func.max(Fst.id)).first() max_id = max_id_result[0] if max_id_result[0] is not None else 0 # 新id为最大id + 1 new_id = max_id + 1 # 创建新的fst记录 new_fst = Fst( id=new_id, name=data['name'], level=data['level'], parent_id=parent_record.id, # 使用查询到的父标签ID annotation=data['annotation'], update_time=datetime.now() ) # 添加到数据库并提交 db.session.add(new_fst) db.session.commit() # 返回成功信息 return jsonify({ 'message': 'Fst record created successfully', 'record': { 'id': new_fst.id, 'name': new_fst.name, 'level': new_fst.level, 'parent_id': new_fst.parent_id, 'parentName': data['parentName'], 'annotation': new_fst.annotation, 'update_time': new_fst.update_time.isoformat() } }), 201 except Exception as e: db.session.rollback() return jsonify({'error': str(e)}), 500 @label_bp.route("/sync-fst", methods=["POST"]) def sync_fst(): # 1. 解析请求参数 params = request.get_json() or {} print(f"【请求参数】原始参数: {params}") name = params.get("name", "") parent_name = params.get("parent_name", "") # 参数校验 if not name or not parent_name: return ( jsonify( { "success": False, "message": "缺少必要参数(name 或 parent_name)", } ), 400, ) # 2. 转发请求配置 API_URL = "http://10.0.240.4:5232/api/fst/update" TIMEOUT = 10 # 超时时间(秒) data = {"name": name, "parent_name": parent_name} try: # 3. 发送转发请求 res = requests.post(url=API_URL, json=data, timeout=TIMEOUT) res.raise_for_status() # 自动抛出 4xx/5xx 状态码的异常 # 4. 处理对方 API 的响应(假设返回 JSON 格式) try: remote_response = res.json() except ValueError: # 对方返回非 JSON 格式响应 return ( jsonify( { "success": False, "message": "同步失败:目标接口返回无效格式", "details": res.text, } ), 500, ) # 5. 返回成功响应 return jsonify( { "success": True, "message": "同步成功", "data": remote_response, # 携带对方 API 的返回数据 } ) except requests.exceptions.RequestException as e: # 捕获所有 requests 相关异常(超时、连接失败、4xx/5xx 等) error_msg = f"同步失败:{str(e)}" print(f"【转发请求错误】{error_msg}") return ( jsonify( { "success": False, "message": error_msg, } ), 500, )