import json from flask import Response, jsonify, request from app.api.data_interface import bp from app.core.data_interface import interface from app.core.graph.graph_operations import ( MyEncoder, connect_graph, create_or_get_node, ) from app.core.llm import code_generate_standard from app.core.meta_data import get_formatted_time, translate_and_parse from app.models.result import failed, success @bp.route("/data/standard/add", methods=["POST"]) def data_standard_add(): try: receiver = request.get_json() name_zh = receiver["name_zh"] name_en = translate_and_parse(name_zh) receiver["name_en"] = name_en[0] receiver["create_time"] = get_formatted_time() receiver["tag"] = json.dumps(receiver["tag"], ensure_ascii=False) create_or_get_node("data_standard", **receiver) res = success("", "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/standard/detail", methods=["POST"]) def data_standard_detail(): try: receiver = request.get_json() nodeid = receiver["id"] # id cql = """MATCH (n:data_standard) where id(n) = $nodeId RETURN properties(n) as property""" # Create a session from the driver returned by connect_graph with connect_graph().session() as session: result = session.run(cql, nodeId=nodeid).single() property = result["property"] if result else {} if "tag" not in property: property["tag"] = None else: property["tag"] = json.loads(property["tag"]) if "describe" not in property: property["describe"] = None res = success(property, "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/standard/code", methods=["POST"]) def data_standard_code(): try: receiver = request.get_json() input = receiver["input"] describe = receiver["describe"] output = receiver["output"] relation = { "input_params": input, "output_params": output, } result = code_generate_standard(describe, relation) res = success(result, "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/standard/update", methods=["POST"]) def data_standard_update(): try: receiver = request.get_json() name_zh = receiver["name_zh"] name_en = translate_and_parse(name_zh) receiver["name_en"] = name_en[0] receiver["create_time"] = get_formatted_time() create_or_get_node("data_standard", **receiver) res = success("", "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/standard/list", methods=["POST"]) def data_standard_list(): try: receiver = request.get_json() page = int(receiver.get("current", 1)) page_size = int(receiver.get("size", 10)) name_en_filter = receiver.get("name_en", None) name_zh_filter = receiver.get("name_zh", None) category = receiver.get("category", None) time = receiver.get("time", None) skip_count = (page - 1) * page_size data, total = interface.standard_list( skip_count, page_size, name_en_filter, name_zh_filter, category, time, ) response_data = { "records": data, "total": total, "size": page_size, "current": page, } res = success(response_data, "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/standard/graph/all", methods=["POST"]) def data_standard_graph_all(): try: receiver = request.get_json() nodeid = receiver["id"] type = receiver["type"] # kinship/impact/all if type == "kinship": result = interface.standard_kinship_graph(nodeid) elif type == "impact": result = interface.standard_impact_graph(nodeid) else: result = interface.standard_all_graph(nodeid) return json.dumps( success(result, "success"), ensure_ascii=False, cls=MyEncoder, ) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/label/add", methods=["POST"]) def data_label_add(): try: receiver = request.get_json() name_zh = receiver["name_zh"] name_en = translate_and_parse(name_zh) receiver["name_en"] = name_en[0] receiver["create_time"] = get_formatted_time() create_or_get_node("DataLabel", **receiver) res = success("", "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/label/detail", methods=["POST"]) def data_label_detail(): try: receiver = request.get_json() nodeid = receiver["id"] # id cql = """MATCH (n:DataLabel) where id(n) = $nodeId RETURN properties(n) as property""" with connect_graph().session() as session: result = session.run(cql, nodeId=nodeid).single() property = result["property"] if result else {} if "describe" not in property: property["describe"] = None # 将传入的节点ID添加到返回信息中 property["id"] = nodeid res = success(property, "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/label/list", methods=["POST"]) def data_label_list(): try: receiver = request.get_json() page = int(receiver.get("current", 1)) page_size = int(receiver.get("size", 10)) name_en_filter = receiver.get("name_en", None) name_zh_filter = receiver.get("name_zh", None) category = receiver.get("category", None) group = receiver.get("group", None) skip_count = (page - 1) * page_size data, total = interface.label_list( skip_count, page_size, name_en_filter, name_zh_filter, category, group, ) response_data = { "records": data, "total": total, "size": page_size, "current": page, } res = success(response_data, "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/labellist", methods=["POST"]) def interface_label_list(): """获取 DataLabel 列表(支持多条件 category_filter 过滤)""" try: receiver = request.get_json() or {} page = int(receiver.get("current", 1)) page_size = int(receiver.get("size", 10)) name_en_filter = receiver.get("name_en") name_zh_filter = receiver.get("name_zh") category_filter = receiver.get("category_filter") group_filter = receiver.get("group") skip_count = (page - 1) * page_size data, total = interface.label_list( skip_count, page_size, name_en_filter, name_zh_filter, category_filter, group_filter, ) # 只保留 id, name_zh, name_en 三个字段 records = [ { "id": item.get("id"), "name_zh": item.get("name_zh"), "name_en": item.get("name_en"), } for item in data ] response_data = { "records": records, "total": total, "size": page_size, "current": page, } res = success(response_data, "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/graphall", methods=["POST"]) def interface_graph_all(): """获取完整关系图谱""" try: receiver = request.get_json() or {} domain_id = receiver.get("id") include_meta = receiver.get("meta", True) if domain_id is None: res = failed("节点ID不能为空") return Response( json.dumps(res, ensure_ascii=False, cls=MyEncoder), mimetype="application/json", ) try: domain_id = int(domain_id) except (ValueError, TypeError): res = failed(f"节点ID必须为整数, 收到的是: {domain_id}") return Response( json.dumps(res, ensure_ascii=False, cls=MyEncoder), mimetype="application/json", ) graph_data = interface.graph_all(domain_id, include_meta) res = success(graph_data) return Response( json.dumps(res, ensure_ascii=False, cls=MyEncoder), mimetype="application/json", ) except Exception as e: res = failed("获取图谱失败", error=str(e)) return Response( json.dumps(res, ensure_ascii=False, cls=MyEncoder), mimetype="application/json", ) @bp.route("/data/label/dynamic/identify", methods=["POST"]) def data_label_dynamic_identify(): try: receiver = request.get_json() name_filter = receiver.get("content", None) data = interface.dynamic_label_list(name_filter) res = success(data, "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/label/graph/all", methods=["POST"]) def data_label_graph(): try: receiver = request.get_json() nodeid = receiver["id"] type = receiver["type"] # kinship/impact/all if type == "kinship": result = interface.label_kinship_graph(nodeid) elif type == "impact": result = interface.label_impact_graph(nodeid) else: result = interface.label_kinship_graph(nodeid) return json.dumps( success(result, "success"), ensure_ascii=False, cls=MyEncoder, ) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/metric/label/standard/delete", methods=["POST"]) def metric_label_standard_delete(): try: receiver = request.get_json() sourceid = receiver["sourceid"] targetid = receiver["targetid"] cql = """ MATCH (source)-[r]-(target) WHERE id(source) = $sourceid AND id(target) = $targetid DELETE r """ with connect_graph().session() as session: session.run(cql, sourceid=sourceid, targetid=targetid) res = success("", "success") return json.dumps(res, ensure_ascii=False, cls=MyEncoder) except Exception as e: res = failed(str(e), 500, {}) return json.dumps(res, ensure_ascii=False, cls=MyEncoder) @bp.route("/data/label/delete", methods=["POST"]) def data_label_delete(): """Delete data label node""" try: receiver = request.get_json() node_id = receiver.get("id") if receiver else None if not node_id: return jsonify(failed("node id is required", 400, {})) try: node_id = int(node_id) except (ValueError, TypeError): return jsonify(failed("node id must be an integer", 400, {})) delete_result = interface.node_delete(node_id) message = delete_result.get("message") or "" if delete_result.get("success"): res = success( { "id": node_id, "message": message, }, "delete success", ) else: res = failed( message, 500, { "id": node_id, "message": message, }, ) return jsonify(res) except Exception as e: return jsonify(failed(f"delete failed: {str(e)}", 500, {}))