refactor(value_rank): 社交关系图改为外部HTML模板渲染
- 新增 social_graph_template_path 配置项,支持独立维护社交图模板路径 - 新增模板文件 plugins/value_rank/templates/social_graph.html,承载关系图样式与占位符 - 移除内嵌模板拼接,改为读取模板文件并进行变量替换后渲染截图
This commit is contained in:
@@ -34,6 +34,7 @@ max_rank_limit = 50
|
|||||||
default_graph_nodes = 12
|
default_graph_nodes = 12
|
||||||
max_graph_nodes = 24
|
max_graph_nodes = 24
|
||||||
graph_edge_pool_limit = 300
|
graph_edge_pool_limit = 300
|
||||||
|
social_graph_template_path = "plugins/value_rank/templates/social_graph.html"
|
||||||
default_trend_days = 7
|
default_trend_days = 7
|
||||||
max_trend_days = 30
|
max_trend_days = 30
|
||||||
|
|
||||||
|
|||||||
@@ -557,6 +557,7 @@ class ValueRankPlugin(MessagePluginInterface):
|
|||||||
self.default_graph_nodes = 12
|
self.default_graph_nodes = 12
|
||||||
self.max_graph_nodes = 24
|
self.max_graph_nodes = 24
|
||||||
self.graph_edge_pool_limit = 300
|
self.graph_edge_pool_limit = 300
|
||||||
|
self.social_graph_template_path = "plugins/value_rank/templates/social_graph.html"
|
||||||
self.default_trend_days = 7
|
self.default_trend_days = 7
|
||||||
self.max_trend_days = 30
|
self.max_trend_days = 30
|
||||||
self.mention_batch_size = 200
|
self.mention_batch_size = 200
|
||||||
@@ -589,6 +590,9 @@ class ValueRankPlugin(MessagePluginInterface):
|
|||||||
self.default_graph_nodes = int(cfg.get("default_graph_nodes", self.default_graph_nodes))
|
self.default_graph_nodes = int(cfg.get("default_graph_nodes", self.default_graph_nodes))
|
||||||
self.max_graph_nodes = int(cfg.get("max_graph_nodes", self.max_graph_nodes))
|
self.max_graph_nodes = int(cfg.get("max_graph_nodes", self.max_graph_nodes))
|
||||||
self.graph_edge_pool_limit = int(cfg.get("graph_edge_pool_limit", self.graph_edge_pool_limit))
|
self.graph_edge_pool_limit = int(cfg.get("graph_edge_pool_limit", self.graph_edge_pool_limit))
|
||||||
|
self.social_graph_template_path = str(
|
||||||
|
cfg.get("social_graph_template_path", self.social_graph_template_path)
|
||||||
|
).strip()
|
||||||
self.default_trend_days = int(cfg.get("default_trend_days", self.default_trend_days))
|
self.default_trend_days = int(cfg.get("default_trend_days", self.default_trend_days))
|
||||||
self.max_trend_days = int(cfg.get("max_trend_days", self.max_trend_days))
|
self.max_trend_days = int(cfg.get("max_trend_days", self.max_trend_days))
|
||||||
self.mention_batch_size = int(cfg.get("mention_batch_size", self.mention_batch_size))
|
self.mention_batch_size = int(cfg.get("mention_batch_size", self.mention_batch_size))
|
||||||
@@ -1241,7 +1245,7 @@ class ValueRankPlugin(MessagePluginInterface):
|
|||||||
partner_map: Dict[str, set],
|
partner_map: Dict[str, set],
|
||||||
node_score_map: Dict[str, float],
|
node_score_map: Dict[str, float],
|
||||||
) -> str:
|
) -> str:
|
||||||
"""构建社交关系图 HTML(含 SVG 节点和边)。"""
|
"""基于模板文件构建社交关系图 HTML(含 SVG 节点和边)。"""
|
||||||
if not selected_nodes:
|
if not selected_nodes:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@@ -1307,69 +1311,34 @@ class ValueRankPlugin(MessagePluginInterface):
|
|||||||
f"关系边:{len(selected_edges)} | 生成时间:{now_text}"
|
f"关系边:{len(selected_edges)} | 生成时间:{now_text}"
|
||||||
)
|
)
|
||||||
|
|
||||||
return f"""
|
# 模板策略说明:
|
||||||
<!DOCTYPE html>
|
# 1. 本插件只走外部模板文件,便于后续视觉同学直接调整样式;
|
||||||
<html lang="zh-CN">
|
# 2. 模板缺失或读取失败时直接返回空字符串,让上层按“生成失败”处理;
|
||||||
<head>
|
# 3. 变量替换使用显式占位符,避免与 CSS 花括号冲突。
|
||||||
<meta charset="UTF-8" />
|
template_path = Path(self.social_graph_template_path)
|
||||||
<style>
|
if not template_path.is_absolute():
|
||||||
body {{
|
template_path = Path.cwd() / template_path
|
||||||
margin: 0;
|
if not template_path.exists():
|
||||||
background: linear-gradient(135deg, #f7fbff 0%, #f2f7ff 45%, #fff8ed 100%);
|
self.LOG.error(f"[{self.name}] 社交图模板不存在: {template_path}")
|
||||||
font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
|
return ""
|
||||||
}}
|
|
||||||
.card {{
|
try:
|
||||||
width: {width}px;
|
template_html = template_path.read_text(encoding="utf-8")
|
||||||
margin: 0 auto;
|
except Exception as e:
|
||||||
padding: 26px 26px 20px 26px;
|
self.LOG.error(f"[{self.name}] 社交图模板读取失败: {template_path}, error={e}")
|
||||||
box-sizing: border-box;
|
return ""
|
||||||
}}
|
|
||||||
.title {{
|
replace_map = {
|
||||||
font-size: 38px;
|
"__WIDTH__": str(width),
|
||||||
color: #1f2d46;
|
"__HEIGHT__": str(height),
|
||||||
font-weight: 800;
|
"__GROUP_TITLE__": group_title,
|
||||||
letter-spacing: 1px;
|
"__SUMMARY_TEXT__": summary_text,
|
||||||
}}
|
"__EDGE_SVG__": "".join(edge_svg_parts),
|
||||||
.subtitle {{
|
"__NODE_SVG__": "".join(node_svg_parts),
|
||||||
margin-top: 8px;
|
}
|
||||||
font-size: 17px;
|
for key, value in replace_map.items():
|
||||||
color: #5f6f8a;
|
template_html = template_html.replace(key, value)
|
||||||
}}
|
return template_html
|
||||||
.graph-wrap {{
|
|
||||||
margin-top: 18px;
|
|
||||||
border-radius: 18px;
|
|
||||||
background: rgba(255, 255, 255, 0.82);
|
|
||||||
border: 1px solid rgba(207, 221, 246, 0.9);
|
|
||||||
box-shadow: 0 8px 24px rgba(58, 82, 130, 0.12);
|
|
||||||
overflow: hidden;
|
|
||||||
}}
|
|
||||||
.legend {{
|
|
||||||
margin-top: 14px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #6f7d96;
|
|
||||||
line-height: 1.7;
|
|
||||||
}}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="card">
|
|
||||||
<div class="title">群友社交关系图</div>
|
|
||||||
<div class="subtitle">{group_title}</div>
|
|
||||||
<div class="subtitle">{summary_text}</div>
|
|
||||||
<div class="graph-wrap">
|
|
||||||
<svg width="{width}" height="{height}" viewBox="0 0 {width} {height}">
|
|
||||||
<rect x="0" y="0" width="{width}" height="{height}" fill="rgba(247,251,255,0.72)"></rect>
|
|
||||||
{''.join(edge_svg_parts)}
|
|
||||||
{''.join(node_svg_parts)}
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="legend">
|
|
||||||
说明:节点越大代表连接群友越多;连线越粗代表互动越强。该图仅基于 @ 关系统计,不含纯文本对话引用关系。
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
|
|
||||||
async def _build_weekly_report_text(self, group_id: str) -> str:
|
async def _build_weekly_report_text(self, group_id: str) -> str:
|
||||||
"""构建“身价周报”文本。
|
"""构建“身价周报”文本。
|
||||||
|
|||||||
61
plugins/value_rank/templates/social_graph.html
Normal file
61
plugins/value_rank/templates/social_graph.html
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background: linear-gradient(135deg, #f7fbff 0%, #f2f7ff 45%, #fff8ed 100%);
|
||||||
|
font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
width: __WIDTH__px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 26px 26px 20px 26px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 38px;
|
||||||
|
color: #1f2d46;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 17px;
|
||||||
|
color: #5f6f8a;
|
||||||
|
}
|
||||||
|
.graph-wrap {
|
||||||
|
margin-top: 18px;
|
||||||
|
border-radius: 18px;
|
||||||
|
background: rgba(255, 255, 255, 0.82);
|
||||||
|
border: 1px solid rgba(207, 221, 246, 0.9);
|
||||||
|
box-shadow: 0 8px 24px rgba(58, 82, 130, 0.12);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.legend {
|
||||||
|
margin-top: 14px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #6f7d96;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="card">
|
||||||
|
<div class="title">群友社交关系图</div>
|
||||||
|
<div class="subtitle">__GROUP_TITLE__</div>
|
||||||
|
<div class="subtitle">__SUMMARY_TEXT__</div>
|
||||||
|
<div class="graph-wrap">
|
||||||
|
<svg width="__WIDTH__" height="__HEIGHT__" viewBox="0 0 __WIDTH__ __HEIGHT__">
|
||||||
|
<rect x="0" y="0" width="__WIDTH__" height="__HEIGHT__" fill="rgba(247,251,255,0.72)"></rect>
|
||||||
|
__EDGE_SVG__
|
||||||
|
__NODE_SVG__
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="legend">
|
||||||
|
说明:节点越大代表连接群友越多;连线越粗代表互动越强。该图仅基于 @ 关系统计,不含纯文本对话引用关系。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user