295 lines
9.1 KiB
Python
295 lines
9.1 KiB
Python
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,
|
||
)
|