import base64
import json
import os
import subprocess
import uuid
from fastapi import HTTPException
from py2neo import Node
from kotei_web_server.neo4j.neo4jdb import Neo4jDBTest
class DevDiagram:
def display_tree(self):
instance = Neo4jDBTest()
query = """MATCH (root:REQModel)
WHERE NOT (root)<-[:include]-()
OPTIONAL MATCH path = (root)-[*]->(descendant)
RETURN root.name AS root_name,ID(root) AS root_identity,labels(root) AS root_labels,
root.update_time AS update_time,root.device_info AS device_info,
CASE WHEN path IS NULL THEN [root] ELSE nodes(path) END AS family"""
results = instance.my_graph.run(query)
trees = self.results_to_tree(results.data())
return trees
def find_node_by_ids_rel(self,nodeIds):
instance = Neo4jDBTest()
results = []
for nodeId in nodeIds:
query = f"""
MATCH (root)
WHERE ID(root)={nodeId}
OPTIONAL MATCH path = (root)-[]-(descendant)
RETURN root.name AS root_name,ID(root) AS root_identity,labels(root) AS root_labels,
root.update_time AS update_time,root.device_info AS device_info,
CASE WHEN path IS NULL THEN [root] ELSE nodes(path) END AS family
"""
results += instance.my_graph.run(query).data()
trees = self.results_to_tree(results)
return trees
def add_to_tree(self, tree, path):
if not path:
return
parent_id = tree.get("id")
node_name = path[0]["name"]
node_id = path[0].identity
labels = list(path[0].labels)
update_time = path[0]["update_time"]
device_info = path[0]["device_info"]
action = path[0]["action"]
# 查找当前节点的子节点中是否已经存在该节点
for child in tree["children"]:
if child["id"] == node_id:
# 继续在这个子节点中添加剩余路径
self.add_to_tree(child, path[1:])
return
# 如果不存在,则创建新的子节点
new_node = {"id": node_id, "labels": labels, "name": node_name, "update_time": update_time,
"device_info": device_info, "children": [], "action": action, "parent_id": parent_id}
tree["children"].append(new_node)
# 继续在新创建的子节点中添加剩余路径
self.add_to_tree(new_node, path[1:])
def results_to_tree(self, results):
trees = {}
for record in results:
root_name = record["root_name"]
family = record["family"]
node_id = record["root_identity"]
labels = record["root_labels"]
update_time = record["update_time"]
device_info = record["device_info"]
# 查找或创建根节点
if node_id not in trees:
trees[node_id] = {"id": node_id, "labels": labels, "name": root_name, "update_time": update_time,
"device_info": device_info, "children": [], "parent_id": -1}
root_tree = trees[node_id]
# 添加路径到树中,去掉第一个节点(根节点)以避免重复
self.add_to_tree(root_tree, family[1:])
return list(trees.values())
def plantuml_to_base64(self, plantuml_text):
try:
# 获取当前文件的目录
current_dir = os.path.dirname(__file__)
# 构建 plantuml.jar 的路径
plantuml_jar_path = os.path.join(current_dir, 'plantuml.jar')
if not os.path.exists(plantuml_jar_path):
raise HTTPException(status_code=500, detail=f"PlantUML JAR not found at {plantuml_jar_path}")
# 调用 PlantUML JAR 包来渲染图像
process = subprocess.Popen(
['java', '-Dfile.encoding=UTF-8', '-jar', plantuml_jar_path, '-pipe'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout_data, stderr_data = process.communicate(input=plantuml_text.encode('utf-8'))
if process.returncode != 0:
raise HTTPException(status_code=500,
detail="Error generating PlantUML diagram: " + stderr_data.decode('utf-8'))
# 将图像数据编码为 Base64
base64_image = base64.b64encode(stdout_data).decode('utf-8')
return base64_image
except Exception as e:
raise HTTPException(status_code=500, detail="Error generating PlantUML diagram: " + str(e))
def display_list(self, root_id, label):
instance = Neo4jDBTest()
if root_id == -1:
labels = [label, 'sdw_dev_design']
nodes = instance.find_all_node(node_type=labels)
# nodes = [dict(node).get('labels',1) for node in nodes]
else:
nodes = self.display_child_list(root_id, label, instance)
return nodes
def display_child_list(self, root_id, child_label, instance):
query = """
MATCH (n) WHERE ID(n) = $root_id
MATCH (n)-[*]->(child:%s)
RETURN DISTINCT ID(child) AS child_id,labels(child) AS child_labels, child
""" % child_label # 注意这里使用字符串拼接来动态构建查询
results = instance.my_graph.run(query, root_id=root_id)
# 处理查询结果
result_list = []
for record in results:
child = dict(record["child"])
child.setdefault("id", record["child_id"])
result_list.append(child)
return result_list
def generate_id(self):
# 生成基于时间的UUID
uuid_time = uuid.uuid1()
# 提取时间戳部分(以100纳秒为单位),转换为毫秒级
timestamp = uuid_time.time // 10 ** 4
return timestamp
# 根据ID获取节点的名称
def get_node_name_by_id(self, node_list, node_id):
for node in node_list:
if node['id'] == node_id:
return node['name']
return None
def build_forest(self, data):
# 创建一个字典来存储所有节点
nodes = {}
# 创建一个列表来存储所有根节点
forest = []
# 先遍历数据列表,创建所有节点字典条目
for item in data:
node_id = item['id']
condition = item.get('condition')
labels = item.get('labels', 'folder')
if node_id not in nodes:
nodes[node_id] = []
nodes[node_id].append(
{'id': node_id, 'name': item['name'], 'children': [],
'parent_id': item.get('parent_id', -1), 'type': item.get('type', 0), 'labels': labels,
'condition': condition})
# 再次遍历数据列表,将每个节点添加到其父节点的子节点列表中
for node_list in nodes.values():
for node in node_list:
parent_id = node['parent_id']
if parent_id == -1:
# 如果没有父节点或父节点ID为-1,则是根节点
forest.append(node)
else:
# 将节点添加到其父节点的子节点列表中
if parent_id in nodes:
for parent_node in nodes[parent_id]:
parent_node['children'].append(node)
return forest
def display_sop_tree(self):
instance = Neo4jDBTest()
query = """MATCH (root:Start)
WHERE NOT (root)<-[:include]-()
OPTIONAL MATCH path = (root)-[*]->(descendant)
RETURN root.name AS root_name,ID(root) AS root_identity,labels(root) AS root_labels,
root.update_time AS update_time,root.device_info AS device_info,
CASE WHEN path IS NULL THEN [root] ELSE nodes(path) END AS family"""
results = instance.my_graph.run(query)
all_nodes = results.data()
trees = self.results_to_tree(all_nodes)
return trees
解析一下