routes.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. from flask import request, jsonify
  2. from app.api.data_model import bp
  3. from app.models.result import success, failed
  4. from app.api.graph.routes import MyEncoder
  5. from app.core.data_model import model as model_functions
  6. import json
  7. # 2024.09.11 数据模型血缘关系(传入数据资源id)
  8. @bp.route('/model/data/relation', methods=['POST'])
  9. def data_model_relation():
  10. try:
  11. # 传入请求参数
  12. receiver = request.get_json()
  13. resource_ids = receiver['id'] # 给定一个数据资源的id
  14. response_data = model_functions.handle_model_relation(resource_ids)
  15. res = success(response_data, "success")
  16. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  17. except Exception as e:
  18. res = failed({}, {"error": f"{e}"})
  19. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  20. # 传入一个数据资源的id,返回多个有血缘关系的数据资源
  21. @bp.route('/model/relatives/relation', methods=['POST'])
  22. def data_relatives_relation():
  23. try:
  24. # 传入请求参数
  25. receiver = request.get_json()
  26. page = int(receiver.get('current', 1))
  27. page_size = int(receiver.get('size', 10))
  28. id = receiver['id']
  29. name_filter = receiver.get('name', None)
  30. category = receiver.get('category', None)
  31. time = receiver.get('time', None)
  32. # 计算跳过的记录的数量
  33. skip_count = (page - 1) * page_size
  34. data, total = model_functions.model_resource_list(skip_count, page_size, name_filter, id, category, time)
  35. response_data = {'records': data, 'total': total, 'size': page_size, 'current': page}
  36. res = success(response_data, "success")
  37. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  38. except Exception as e:
  39. res = failed({}, {"error": f"{e}"})
  40. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  41. # DDL数据模型保存
  42. @bp.route('/data/model/save', methods=['POST'])
  43. def data_model_save():
  44. # 传入请求参数
  45. receiver = request.get_json()
  46. data_model = receiver['name']
  47. id_list = receiver['id_list']
  48. # resource_id和meta_id构成json格式
  49. result = json.dumps(id_list, ensure_ascii=False)
  50. try:
  51. # 从DDL中选取保存数据模型
  52. result_list = [receiver['en_name']]
  53. id, data_model_node = model_functions.handle_data_model(data_model, result_list, result, receiver)
  54. model_functions.handle_no_meta_data_model(id_list, receiver, data_model_node)
  55. model_functions.calculate_model_level(id)
  56. res = success({}, "success")
  57. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  58. except Exception as e:
  59. res = failed({}, {"error": f"{e}"})
  60. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  61. # 新建数据模型请求接口(从数据资源中选取)
  62. # @bp.route('/model/data/search', methods=['POST'])
  63. @bp.route('/data/search', methods=['POST'])
  64. def data_model_search():
  65. # 传入请求参数
  66. receiver = request.get_json()
  67. data_model = receiver['name']
  68. id_list = receiver['id_list']
  69. # resource_id和meta_id构成json格式
  70. result = json.dumps(id_list, ensure_ascii=False)
  71. try:
  72. from app.core.meta_data import translate_and_parse
  73. result_list = translate_and_parse(data_model)
  74. id, data_model_node = model_functions.handle_data_model(data_model, result_list, result, receiver)
  75. if id_list:
  76. model_functions.resource_handle_meta_data_model(id_list, id)
  77. model_functions.calculate_model_level(id)
  78. res = success({}, "success")
  79. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  80. except Exception as e:
  81. res = failed({}, {"error": f"{e}"})
  82. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  83. # 新建数据模型请求接口(从数据模型中选取)
  84. @bp.route('/model/data/model/add', methods=['POST'])
  85. def data_model_model_add():
  86. # 传入请求参数
  87. receiver = request.get_json()
  88. data_model = receiver['name']
  89. id_list = receiver['id_list']
  90. # model_id和meta_id构成json格式
  91. result = json.dumps(id_list, ensure_ascii=False)
  92. try:
  93. from app.core.meta_data import translate_and_parse
  94. result_list = translate_and_parse(data_model)
  95. node_id, data_model_node = model_functions.handle_data_model(data_model, result_list, result, receiver)
  96. model_functions.model_handle_meta_data_model(id_list, node_id)
  97. model_functions.calculate_model_level(node_id)
  98. # 构建响应数据
  99. response_data = {
  100. "id": node_id,
  101. "name": data_model_node.get('name'),
  102. "en_name": data_model_node.get('en_name'),
  103. "description": data_model_node.get('description'),
  104. "category": data_model_node.get('category'),
  105. "time": data_model_node.get('time'),
  106. "level": data_model_node.get('level'),
  107. "tag": data_model_node.get('tag'),
  108. "childrenId": data_model_node.get('childrenId', []),
  109. "leader": data_model_node.get('leader'),
  110. "origin": data_model_node.get('origin'),
  111. "frequency": data_model_node.get('frequency'),
  112. "organization": data_model_node.get('organization'),
  113. "data_sensitivity": data_model_node.get('data_sensitivity'),
  114. "status": data_model_node.get('status')
  115. }
  116. res = success(response_data, "success")
  117. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  118. except Exception as e:
  119. res = failed({}, {"error": f"{e}"})
  120. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  121. # 数据模型-详情接口
  122. @bp.route('/data/model/detail', methods=['POST'])
  123. def data_model_detail():
  124. try:
  125. # 传入请求参数
  126. receiver = request.get_json()
  127. # 直接使用字符串ID,不做类型转换
  128. id = receiver.get('id')
  129. print(f"Received id from frontend: {id}")
  130. response_data = model_functions.handle_id_model(id)
  131. res = success(response_data, "success")
  132. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  133. except Exception as e:
  134. import traceback
  135. traceback.print_exc()
  136. res = failed({}, {"error": f"{e}"})
  137. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  138. # 删除数据模型
  139. @bp.route('/data/model/delete', methods=['POST'])
  140. def data_model_delete():
  141. try:
  142. # 传入请求参数
  143. receiver = request.get_json()
  144. id = receiver.get('id')
  145. print(f"Deleting data model with id: {id}")
  146. # 首先删除数据模型节点
  147. from app.services.neo4j_driver import neo4j_driver
  148. query = """
  149. MATCH (n:data_model) where id(n) = $nodeId
  150. detach delete n
  151. """
  152. with neo4j_driver.get_session() as session:
  153. session.run(query, nodeId=id)
  154. res = success({}, "success")
  155. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  156. except Exception as e:
  157. import traceback
  158. traceback.print_exc()
  159. res = failed({}, {"error": f"{e}"})
  160. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  161. # 列表 数据模型查询
  162. @bp.route('/data/model/list', methods=['POST'])
  163. def data_model_list():
  164. try:
  165. # 传入请求参数
  166. receiver = request.get_json()
  167. page = int(receiver.get('current', 1))
  168. page_size = int(receiver.get('size', 10))
  169. name_filter = receiver.get('name', None)
  170. en_name_filter = receiver.get('en_name', None)
  171. category = receiver.get('category', None)
  172. tag = receiver.get('tag', None)
  173. level = receiver.get('level', None)
  174. # 计算跳过的记录的数量
  175. skip_count = (page - 1) * page_size
  176. data, total = model_functions.model_list(skip_count, page_size, en_name_filter,
  177. name_filter, category, tag, level)
  178. response_data = {'records': data, 'total': total, 'size': page_size, 'current': page}
  179. res = success(response_data, "success")
  180. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  181. except Exception as e:
  182. res = failed({}, {"error": f"{e}"})
  183. return json.dumps(res, ensure_ascii=False, cls=MyEncoder)
  184. # 数据模型的图谱(血缘关系Kinship+影响关系Impact+所有关系all)
  185. @bp.route('/data/model/graph/all', methods=['POST'])
  186. def data_model_graph_all():
  187. try:
  188. # 传入请求参数
  189. receiver = request.get_json()
  190. nodeid = receiver['id']
  191. type = receiver['type'] # kinship/impact/all
  192. meta = receiver['meta'] # true/false 是否返回元数据
  193. if type == 'kinship':
  194. result = model_functions.model_kinship_graph(nodeid, meta)
  195. elif type == 'impact':
  196. result = model_functions.model_impact_graph(nodeid, meta)
  197. else:
  198. result = model_functions.model_all_graph(nodeid, meta)
  199. return json.dumps(success(result, "success"), ensure_ascii=False, cls=MyEncoder)
  200. except Exception as e:
  201. return json.dumps(failed({}, str(e)), ensure_ascii=False, cls=MyEncoder)
  202. # 数据模型的列表图谱
  203. @bp.route('/data/model/list/graph', methods=['POST'])
  204. def data_model_list_graph():
  205. try:
  206. # 传入请求参数
  207. receiver = request.get_json()
  208. if not receiver or 'tag' not in receiver:
  209. raise ValueError("Missing 'tag' parameter in request body")
  210. nodeid = receiver['tag']
  211. # 构建查询条件
  212. params = {}
  213. where_clause = ""
  214. if nodeid is not None:
  215. where_clause = "MATCH (n)-[:label]->(la) WHERE id(la) = $nodeId"
  216. params['nodeId'] = nodeid
  217. from app.services.neo4j_driver import neo4j_driver
  218. query = f"""
  219. MATCH (n:data_model)
  220. OPTIONAL MATCH (n)-[:child]->(child)
  221. {where_clause}
  222. WITH
  223. collect(DISTINCT {{id: toString(id(n)), text: n.name, type: split(labels(n)[0], '_')[1]}}) AS nodes,
  224. collect(DISTINCT {{id: toString(id(child)), text: child.name, type: split(labels(child)[0], '_')[1]}}) AS nodes2,
  225. collect(DISTINCT {{from: toString(id(n)), to: toString(id(child)), text: '下级'}}) AS lines
  226. RETURN nodes + nodes2 AS nodes, lines AS lines
  227. """
  228. with neo4j_driver.get_session() as session:
  229. result = session.run(query, **params)
  230. data = result.data()
  231. if len(data) > 0:
  232. # 过滤掉空节点(即 id 为 null 的节点)
  233. nodes = []
  234. for node in data[0]['nodes']:
  235. if node['id'] != 'null':
  236. nodes.append(node)
  237. lines = data[0]['lines']
  238. response_data = {
  239. 'nodes': nodes,
  240. 'edges': lines
  241. }
  242. return json.dumps(success(response_data, "success"), ensure_ascii=False, cls=MyEncoder)
  243. else:
  244. return json.dumps(success({'nodes': [], 'edges': []}, "No data found"), ensure_ascii=False, cls=MyEncoder)
  245. except Exception as e:
  246. return json.dumps(failed({}, str(e)), ensure_ascii=False, cls=MyEncoder)
  247. # 更新数据模型
  248. @bp.route('/data/model/update', methods=['POST'])
  249. def data_model_update():
  250. try:
  251. # 传入请求参数
  252. receiver = request.get_json()
  253. result = model_functions.data_model_edit(receiver)
  254. return json.dumps(success(result, "success"), ensure_ascii=False, cls=MyEncoder)
  255. except Exception as e:
  256. return json.dumps(failed({}, str(e)), ensure_ascii=False, cls=MyEncoder)