routes.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. import json
  2. from flask import Response, jsonify, request
  3. from app.api.data_interface import bp
  4. from app.core.data_interface import interface
  5. from app.core.graph.graph_operations import (
  6. MyEncoder,
  7. connect_graph,
  8. create_or_get_node,
  9. )
  10. from app.core.llm import code_generate_standard
  11. from app.core.meta_data import get_formatted_time, translate_and_parse
  12. from app.models.result import failed, success
  13. @bp.route("/data/standard/add", methods=["POST"])
  14. def data_standard_add():
  15. try:
  16. receiver = request.get_json()
  17. name_zh = receiver["name_zh"]
  18. name_en = translate_and_parse(name_zh)
  19. receiver["name_en"] = name_en[0]
  20. receiver["create_time"] = get_formatted_time()
  21. receiver["tag"] = json.dumps(receiver["tag"], ensure_ascii=False)
  22. create_or_get_node("data_standard", **receiver)
  23. res = success("", "success")
  24. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  25. except Exception as e:
  26. res = failed(str(e), 500, {})
  27. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  28. @bp.route("/data/standard/detail", methods=["POST"])
  29. def data_standard_detail():
  30. try:
  31. receiver = request.get_json()
  32. nodeid = receiver["id"] # id
  33. cql = """MATCH (n:data_standard) where id(n) = $nodeId
  34. RETURN properties(n) as property"""
  35. # Create a session from the driver returned by connect_graph
  36. with connect_graph().session() as session:
  37. result = session.run(cql, nodeId=nodeid).single()
  38. property = result["property"] if result else {}
  39. if "tag" not in property:
  40. property["tag"] = None
  41. else:
  42. property["tag"] = json.loads(property["tag"])
  43. if "describe" not in property:
  44. property["describe"] = None
  45. res = success(property, "success")
  46. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  47. except Exception as e:
  48. res = failed(str(e), 500, {})
  49. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  50. @bp.route("/data/standard/code", methods=["POST"])
  51. def data_standard_code():
  52. try:
  53. receiver = request.get_json()
  54. input = receiver["input"]
  55. describe = receiver["describe"]
  56. output = receiver["output"]
  57. relation = {
  58. "input_params": input,
  59. "output_params": output,
  60. }
  61. result = code_generate_standard(describe, relation)
  62. res = success(result, "success")
  63. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  64. except Exception as e:
  65. res = failed(str(e), 500, {})
  66. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  67. @bp.route("/data/standard/update", methods=["POST"])
  68. def data_standard_update():
  69. try:
  70. receiver = request.get_json()
  71. name_zh = receiver["name_zh"]
  72. name_en = translate_and_parse(name_zh)
  73. receiver["name_en"] = name_en[0]
  74. receiver["create_time"] = get_formatted_time()
  75. create_or_get_node("data_standard", **receiver)
  76. res = success("", "success")
  77. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  78. except Exception as e:
  79. res = failed(str(e), 500, {})
  80. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  81. @bp.route("/data/standard/list", methods=["POST"])
  82. def data_standard_list():
  83. try:
  84. receiver = request.get_json()
  85. page = int(receiver.get("current", 1))
  86. page_size = int(receiver.get("size", 10))
  87. name_en_filter = receiver.get("name_en", None)
  88. name_zh_filter = receiver.get("name_zh", None)
  89. category = receiver.get("category", None)
  90. time = receiver.get("time", None)
  91. skip_count = (page - 1) * page_size
  92. data, total = interface.standard_list(
  93. skip_count,
  94. page_size,
  95. name_en_filter,
  96. name_zh_filter,
  97. category,
  98. time,
  99. )
  100. response_data = {
  101. "records": data,
  102. "total": total,
  103. "size": page_size,
  104. "current": page,
  105. }
  106. res = success(response_data, "success")
  107. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  108. except Exception as e:
  109. res = failed(str(e), 500, {})
  110. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  111. @bp.route("/data/standard/graph/all", methods=["POST"])
  112. def data_standard_graph_all():
  113. try:
  114. receiver = request.get_json()
  115. nodeid = receiver["id"]
  116. type = receiver["type"] # kinship/impact/all
  117. if type == "kinship":
  118. result = interface.standard_kinship_graph(nodeid)
  119. elif type == "impact":
  120. result = interface.standard_impact_graph(nodeid)
  121. else:
  122. result = interface.standard_all_graph(nodeid)
  123. return json.dumps(
  124. success(result, "success"),
  125. ensure_ascii=False,
  126. cls=MyEncoder,
  127. )
  128. except Exception as e:
  129. res = failed(str(e), 500, {})
  130. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  131. @bp.route("/data/label/add", methods=["POST"])
  132. def data_label_add():
  133. try:
  134. receiver = request.get_json()
  135. name_zh = receiver["name_zh"]
  136. name_en = translate_and_parse(name_zh)
  137. receiver["name_en"] = name_en[0]
  138. receiver["create_time"] = get_formatted_time()
  139. create_or_get_node("DataLabel", **receiver)
  140. res = success("", "success")
  141. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  142. except Exception as e:
  143. res = failed(str(e), 500, {})
  144. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  145. @bp.route("/data/label/detail", methods=["POST"])
  146. def data_label_detail():
  147. try:
  148. receiver = request.get_json()
  149. nodeid = receiver["id"] # id
  150. cql = """MATCH (n:DataLabel) where id(n) = $nodeId
  151. RETURN properties(n) as property"""
  152. with connect_graph().session() as session:
  153. result = session.run(cql, nodeId=nodeid).single()
  154. property = result["property"] if result else {}
  155. if "describe" not in property:
  156. property["describe"] = None
  157. # 将传入的节点ID添加到返回信息中
  158. property["id"] = nodeid
  159. res = success(property, "success")
  160. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  161. except Exception as e:
  162. res = failed(str(e), 500, {})
  163. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  164. @bp.route("/data/label/list", methods=["POST"])
  165. def data_label_list():
  166. try:
  167. receiver = request.get_json()
  168. page = int(receiver.get("current", 1))
  169. page_size = int(receiver.get("size", 10))
  170. name_en_filter = receiver.get("name_en", None)
  171. name_zh_filter = receiver.get("name_zh", None)
  172. category = receiver.get("category", None)
  173. group = receiver.get("group", None)
  174. skip_count = (page - 1) * page_size
  175. data, total = interface.label_list(
  176. skip_count,
  177. page_size,
  178. name_en_filter,
  179. name_zh_filter,
  180. category,
  181. group,
  182. )
  183. response_data = {
  184. "records": data,
  185. "total": total,
  186. "size": page_size,
  187. "current": page,
  188. }
  189. res = success(response_data, "success")
  190. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  191. except Exception as e:
  192. res = failed(str(e), 500, {})
  193. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  194. @bp.route("/labellist", methods=["POST"])
  195. def interface_label_list():
  196. """获取 DataLabel 列表(支持多条件 category_filter 过滤)"""
  197. try:
  198. receiver = request.get_json() or {}
  199. page = int(receiver.get("current", 1))
  200. page_size = int(receiver.get("size", 10))
  201. name_en_filter = receiver.get("name_en")
  202. name_zh_filter = receiver.get("name_zh")
  203. category_filter = receiver.get("category_filter")
  204. group_filter = receiver.get("group")
  205. skip_count = (page - 1) * page_size
  206. data, total = interface.label_list(
  207. skip_count,
  208. page_size,
  209. name_en_filter,
  210. name_zh_filter,
  211. category_filter,
  212. group_filter,
  213. )
  214. # 只保留 id, name_zh, name_en 三个字段
  215. records = [
  216. {
  217. "id": item.get("id"),
  218. "name_zh": item.get("name_zh"),
  219. "name_en": item.get("name_en"),
  220. }
  221. for item in data
  222. ]
  223. response_data = {
  224. "records": records,
  225. "total": total,
  226. "size": page_size,
  227. "current": page,
  228. }
  229. res = success(response_data, "success")
  230. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  231. except Exception as e:
  232. res = failed(str(e), 500, {})
  233. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  234. @bp.route("/graphall", methods=["POST"])
  235. def interface_graph_all():
  236. """获取完整关系图谱"""
  237. try:
  238. receiver = request.get_json() or {}
  239. domain_id = receiver.get("id")
  240. include_meta = receiver.get("meta", True)
  241. if domain_id is None:
  242. res = failed("节点ID不能为空")
  243. return Response(
  244. json.dumps(res, ensure_ascii=False, cls=MyEncoder),
  245. mimetype="application/json",
  246. )
  247. try:
  248. domain_id = int(domain_id)
  249. except (ValueError, TypeError):
  250. res = failed(f"节点ID必须为整数, 收到的是: {domain_id}")
  251. return Response(
  252. json.dumps(res, ensure_ascii=False, cls=MyEncoder),
  253. mimetype="application/json",
  254. )
  255. graph_data = interface.graph_all(domain_id, include_meta)
  256. res = success(graph_data)
  257. return Response(
  258. json.dumps(res, ensure_ascii=False, cls=MyEncoder),
  259. mimetype="application/json",
  260. )
  261. except Exception as e:
  262. res = failed("获取图谱失败", error=str(e))
  263. return Response(
  264. json.dumps(res, ensure_ascii=False, cls=MyEncoder),
  265. mimetype="application/json",
  266. )
  267. @bp.route("/data/label/dynamic/identify", methods=["POST"])
  268. def data_label_dynamic_identify():
  269. try:
  270. receiver = request.get_json()
  271. name_filter = receiver.get("content", None)
  272. data = interface.dynamic_label_list(name_filter)
  273. res = success(data, "success")
  274. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  275. except Exception as e:
  276. res = failed(str(e), 500, {})
  277. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  278. @bp.route("/data/label/graph/all", methods=["POST"])
  279. def data_label_graph():
  280. try:
  281. receiver = request.get_json()
  282. nodeid = receiver["id"]
  283. type = receiver["type"] # kinship/impact/all
  284. if type == "kinship":
  285. result = interface.label_kinship_graph(nodeid)
  286. elif type == "impact":
  287. result = interface.label_impact_graph(nodeid)
  288. else:
  289. result = interface.label_kinship_graph(nodeid)
  290. return json.dumps(
  291. success(result, "success"),
  292. ensure_ascii=False,
  293. cls=MyEncoder,
  294. )
  295. except Exception as e:
  296. res = failed(str(e), 500, {})
  297. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  298. @bp.route("/metric/label/standard/delete", methods=["POST"])
  299. def metric_label_standard_delete():
  300. try:
  301. receiver = request.get_json()
  302. sourceid = receiver["sourceid"]
  303. targetid = receiver["targetid"]
  304. cql = """
  305. MATCH (source)-[r]-(target)
  306. WHERE id(source) = $sourceid AND id(target) = $targetid
  307. DELETE r
  308. """
  309. with connect_graph().session() as session:
  310. session.run(cql, sourceid=sourceid, targetid=targetid)
  311. res = success("", "success")
  312. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  313. except Exception as e:
  314. res = failed(str(e), 500, {})
  315. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  316. @bp.route("/data/label/delete", methods=["POST"])
  317. def data_label_delete():
  318. """Delete data label node"""
  319. try:
  320. receiver = request.get_json()
  321. node_id = receiver.get("id") if receiver else None
  322. if not node_id:
  323. return jsonify(failed("node id is required", 400, {}))
  324. try:
  325. node_id = int(node_id)
  326. except (ValueError, TypeError):
  327. return jsonify(failed("node id must be an integer", 400, {}))
  328. delete_result = interface.node_delete(node_id)
  329. message = delete_result.get("message") or ""
  330. if delete_result.get("success"):
  331. res = success(
  332. {
  333. "id": node_id,
  334. "message": message,
  335. },
  336. "delete success",
  337. )
  338. else:
  339. res = failed(
  340. message,
  341. 500,
  342. {
  343. "id": node_id,
  344. "message": message,
  345. },
  346. )
  347. return jsonify(res)
  348. except Exception as e:
  349. return jsonify(failed(f"delete failed: {str(e)}", 500, {}))