You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

237 lines
9.9 KiB

# service/GraphStyleService.py
import json
from util.mysql_utils import mysql_client
class GraphStyleService:
@staticmethod
def save_config(canvas_name: str, current_label: str, styles_dict: dict, group_name: str = None, config_id: int = None) -> bool:
"""
保存图谱样式配置(修复版:防止自动保存导致的分组乱跑)
"""
# 2. 转换样式 JSON
config_json = json.dumps(styles_dict, ensure_ascii=False)
# 3. 【核心修改点】:区分 更新 还是 新建
if config_id:
# --- 更新逻辑 ---
# 如果带了 ID,我们要极其谨慎地处理 group_id,防止在自动保存时被误改
# A. 如果调用者明确传了 group_name,说明是“移动”或“初次保存到某组”
if group_name and group_name.strip() != "":
# 检查/创建 目标方案组
check_group_sql = "SELECT id FROM graph_style_groups WHERE group_name = %s LIMIT 1"
existing_group = mysql_client.execute_query(check_group_sql, (group_name,))
if existing_group:
target_group_id = existing_group[0]['id']
else:
create_group_sql = "INSERT INTO graph_style_groups (group_name, is_active, is_default) VALUES (%s, %s, %s)"
mysql_client.execute_update(create_group_sql, (group_name, False, False))
target_group_id = mysql_client.execute_query("SELECT LAST_INSERT_ID() as last_id")[0]['last_id']
# 执行带分组更新的 SQL
sql = """
UPDATE graph_configs
SET canvas_name = %s, current_label = %s, config_json = %s, group_id = %s
WHERE id = %s
"""
affected_rows = mysql_client.execute_update(sql, (canvas_name, current_label, config_json, target_group_id, config_id))
else:
# B. 如果没有传 group_name,说明是“实时自动保存”,严禁修改 group_id
# 这样即使前端变量乱了,数据库的分组也不会变
sql = """
UPDATE graph_configs
SET canvas_name = %s, current_label = %s, config_json = %s
WHERE id = %s
"""
affected_rows = mysql_client.execute_update(sql, (canvas_name, current_label, config_json, config_id))
else:
# --- 新建逻辑 ---
# 新建时必须有组名,默认“默认方案”
if not group_name or group_name.strip() == "":
group_name = "默认方案"
check_group_sql = "SELECT id FROM graph_style_groups WHERE group_name = %s LIMIT 1"
existing_group = mysql_client.execute_query(check_group_sql, (group_name,))
if existing_group:
target_group_id = existing_group[0]['id']
else:
create_group_sql = "INSERT INTO graph_style_groups (group_name, is_active, is_default) VALUES (%s, %s, %s)"
mysql_client.execute_update(create_group_sql, (group_name, False, False))
target_group_id = mysql_client.execute_query("SELECT LAST_INSERT_ID() as last_id")[0]['last_id']
sql = """
INSERT INTO graph_configs (canvas_name, current_label, config_json, group_id)
VALUES (%s, %s, %s, %s)
"""
affected_rows = mysql_client.execute_update(sql, (canvas_name, current_label, config_json, target_group_id))
return affected_rows > 0
@staticmethod
def get_grouped_configs() -> list:
"""
获取嵌套结构的方案列表,按默认/激活状态排序
"""
groups_sql = """
SELECT id, group_name, is_active, is_default
FROM graph_style_groups
ORDER BY is_default DESC, id ASC
"""
groups = mysql_client.execute_query(groups_sql) or []
configs_sql = "SELECT id, group_id, canvas_name, current_label, config_json, create_time FROM graph_configs"
configs = mysql_client.execute_query(configs_sql) or []
for conf in configs:
if conf.get('config_json'):
try:
conf['styles'] = json.loads(conf['config_json'])
except:
conf['styles'] = {}
del conf['config_json']
if conf.get('create_time') and not isinstance(conf['create_time'], str):
conf['create_time'] = conf['create_time'].strftime('%Y-%m-%d %H:%M:%S')
result = []
for g in groups:
g['is_active'] = bool(g['is_active'])
g['is_default'] = bool(g['is_default'])
g_children = [c for c in configs if c['group_id'] == g['id']]
g['configs'] = g_children
g['expanded'] = g['is_active']
result.append(g)
return result
@staticmethod
def get_active_configs() -> list:
"""
获取 is_active = 1 的方案组及其配置项
返回长度为 0 或 1 的列表(因为通常只有一个激活组)
"""
# 1. 查询 is_active = 1 的组(按 id 排序,取第一个以防有多个)
group_sql = """
SELECT id, group_name, is_active, is_default
FROM graph_style_groups
WHERE is_active = 1
ORDER BY id ASC
LIMIT 1
"""
groups = mysql_client.execute_query(group_sql) or []
if not groups:
return [] # 没有激活的组
group = groups[0]
group_id = group['id']
# 2. 查询该组下的所有配置
configs_sql = """
SELECT id, group_id, canvas_name, current_label, config_json, create_time
FROM graph_configs
WHERE group_id = %s
"""
configs = mysql_client.execute_query(configs_sql, (group_id,)) or []
# 3. 处理配置项
for conf in configs:
if conf.get('config_json'):
try:
conf['styles'] = json.loads(conf['config_json'])
except (TypeError, ValueError):
conf['styles'] = {}
del conf['config_json']
if conf.get('create_time') and not isinstance(conf['create_time'], str):
conf['create_time'] = conf['create_time'].strftime('%Y-%m-%d %H:%M:%S')
# 4. 组装结果
group['configs'] = configs
return [group] # 返回单元素列表,保持接口兼容性
@staticmethod
def apply_group_all(group_id: int) -> bool:
"""应用全案:设置激活状态"""
try:
reset_sql = "UPDATE graph_style_groups SET is_active = %s"
mysql_client.execute_update(reset_sql, (False,))
apply_sql = "UPDATE graph_style_groups SET is_active = %s WHERE id = %s"
affected_rows = mysql_client.execute_update(apply_sql, (True, group_id))
return affected_rows > 0
except Exception as e:
print(f"Apply group error: {e}")
return False
@staticmethod
def set_default_group(group_id: int) -> bool:
"""设为系统初始默认方案"""
try:
reset_sql = "UPDATE graph_style_groups SET is_default = %s"
mysql_client.execute_update(reset_sql, (False,))
set_sql = "UPDATE graph_style_groups SET is_default = %s WHERE id = %s"
affected_rows = mysql_client.execute_update(set_sql, (True, group_id))
return affected_rows > 0
except Exception as e:
print(f"Set default error: {e}")
return False
@staticmethod
def get_all_configs() -> list:
"""获取扁平查询"""
sql = """
SELECT c.id, c.group_id, c.canvas_name, c.current_label, c.config_json, c.create_time, g.is_active
FROM graph_configs c
LEFT JOIN graph_style_groups g ON c.group_id = g.id
ORDER BY c.create_time DESC
"""
rows = mysql_client.execute_query(sql)
if not rows: return []
for row in rows:
if row.get('config_json'):
try:
row['styles'] = json.loads(row['config_json'])
except:
row['styles'] = {}
del row['config_json']
if row.get('create_time') and not isinstance(row['create_time'], str):
row['create_time'] = row['create_time'].strftime('%Y-%m-%d %H:%M:%S')
row['is_active'] = bool(row.get('is_active', False))
return rows
@staticmethod
def delete_group(group_id: int) -> bool:
"""级联删除"""
del_configs_sql = "DELETE FROM graph_configs WHERE group_id = %s"
mysql_client.execute_update(del_configs_sql, (group_id,))
del_group_sql = "DELETE FROM graph_style_groups WHERE id = %s"
affected_rows = mysql_client.execute_update(del_group_sql, (group_id,))
return affected_rows > 0
@staticmethod
def delete_config(config_id: int) -> bool:
"""删除配置"""
sql = "DELETE FROM graph_configs WHERE id = %s"
affected_rows = mysql_client.execute_update(sql, (config_id,))
return affected_rows > 0
@staticmethod
def batch_delete_configs(config_ids: list) -> int:
"""批量删除"""
if not config_ids: return 0
try:
clean_ids = [int(cid) for cid in config_ids if str(cid).isdigit()]
except: return 0
if not clean_ids: return 0
placeholders = ', '.join(['%s'] * len(clean_ids))
sql = f"DELETE FROM graph_configs WHERE id IN ({placeholders})"
return mysql_client.execute_update(sql, tuple(clean_ids))
@staticmethod
def get_group_list() -> list:
"""获取方案列表"""
sql = "SELECT id, group_name, is_active, is_default FROM graph_style_groups ORDER BY is_default DESC, id DESC"
return mysql_client.execute_query(sql) or []