diff --git a/plugins/value_rank/main.py b/plugins/value_rank/main.py
index 3ece5fd..8ddeff7 100644
--- a/plugins/value_rank/main.py
+++ b/plugins/value_rank/main.py
@@ -1314,8 +1314,12 @@ class ValueRankPlugin(MessagePluginInterface):
f'stroke="rgba(33, 150, 243, {opacity:.3f})" stroke-width="{stroke_width:.2f}" />'
)
+ # 节点头像层拆分为 defs + body 两段:
+ # 1. defs 内定义每个节点的裁剪路径,避免头像越界;
+ # 2. body 里再引用 image/圆环/文案,便于模板层做结构化插槽替换。
+ node_defs_parts: List[str] = []
node_svg_parts: List[str] = []
- for uid in selected_nodes:
+ for idx, uid in enumerate(selected_nodes, start=1):
x, y = pos_map[uid]
partner_count = len(partner_map.get(uid, set()))
score = float(node_score_map.get(uid, 0.0))
@@ -1323,11 +1327,39 @@ class ValueRankPlugin(MessagePluginInterface):
node_radius = 18.0 + 24.0 * size_norm
nick = cm.get_group_name(group_id, uid) or uid
safe_nick = html.escape(str(nick))
+ avatar_url = str(cm.get_head_image(uid) or "").strip()
+ # 使用“连接度越高环线越偏暖”的视觉策略,帮助快速识别核心节点。
+ ring_color = "rgba(255, 152, 0, 0.95)" if size_norm >= 0.6 else "rgba(79, 123, 201, 0.95)"
node_svg_parts.append(
- f''
+ f''
)
+
+ if avatar_url:
+ # 有头像时,使用 SVG clipPath 裁剪成圆形头像,既美观又保持节点尺寸可变。
+ safe_avatar_url = html.escape(avatar_url, quote=True)
+ clip_id = f"avatar_clip_{idx}"
+ avatar_r = max(node_radius - 1.8, 8.0)
+ node_defs_parts.append(
+ f''
+ )
+ node_svg_parts.append(
+ f''
+ )
+ else:
+ # 无头像时回退为字符节点,保证图谱渲染完整可用。
+ node_svg_parts.append(
+ f''
+ )
+ node_svg_parts.append(
+ f''
+ f'{html.escape(str(nick)[:1] or "?")}'
+ )
+
node_svg_parts.append(
f'{safe_nick}'
@@ -1367,6 +1399,7 @@ class ValueRankPlugin(MessagePluginInterface):
"__GROUP_TITLE__": group_title,
"__SUMMARY_TEXT__": summary_text,
"__EDGE_SVG__": "".join(edge_svg_parts),
+ "__NODE_DEFS__": "".join(node_defs_parts),
"__NODE_SVG__": "".join(node_svg_parts),
}
for key, value in replace_map.items():
diff --git a/plugins/value_rank/templates/social_design.md b/plugins/value_rank/templates/social_design.md
new file mode 100644
index 0000000..6fdbc8d
--- /dev/null
+++ b/plugins/value_rank/templates/social_design.md
@@ -0,0 +1,80 @@
+为了指导研发团队实现这个**“群聊社交关系图(Social Network Analysis, SNA)”**插件,我为你起草了一份技术设计文档(Markdown 格式)。这份文档涵盖了从数据采集、核心算法到可视化渲染的全流程。
+
+---
+
+# 插件开发指引:群聊社交关系图 (Social Network Analysis)
+
+## 1. 需求背景
+通过对群聊中用户间的互动(@、回复、共同话题)进行建模,生成一张直观的社交关系图。旨在通过可视化“小圈子”、“核心人物”和“舔狗指数”,提升群成员的互动欲望和社群归属感。
+
+## 2. 核心逻辑架构
+
+
+### 2.1 数据采集层 (Data Collection)
+需要监听群聊消息流,提取以下关键信息:
+* **发送者 (Sender ID)**
+* **接收者 (Target ID)**:通过正则表达式提取消息中的 `@昵称` 或对特定消息的“回复”。
+* **互动频率 (Weight)**:记录 A 与 B 之间互动的累计次数。
+* **情感倾向 (Sentiment)**:可选,利用现有的 AI 能力判断互动是“友好”还是“对立”。
+
+### 2.2 核心算法层 (Processing)
+使用 **图论 (Graph Theory)** 对数据进行建模:
+* **节点 (Node)**:每个群成员为一个节点。
+ * *计算指标:* **度中心性 (Degree Centrality)**。被连接数越多,节点在图中越大。
+* **连线 (Edge)**:成员间的互动。
+ * *计算指标:* **权重 (Weight)**。互动频率越高,线段越粗。
+ * *方向性:* 区分单向(A -> B)和双向(A <-> B)。
+
+### 2.3 可视化渲染层 (Visualization)
+采用 **力导向布局算法 (Force-Directed Layout)**。
+* **算法原理:** 互动的节点产生引力,非互动节点产生斥力,最终达到动态平衡。
+* **视觉编码规则:**
+ 1. **节点大小** $\propto$ 影响力指数。
+ 2. **边框颜色** = 联动“身价排行榜”等级(如:金/银/铜/灰)。
+ 3. **线段粗细** $\propto$ 互动频率。
+ 4. **线段颜色** = 情感值(绿色-亲密,灰色-普通,红色-冲突)。
+
+## 3. 技术栈建议
+* **后端计算:** Python (`NetworkX`) —— 强大的图计算库,支持各种中心性算法。
+* **图像渲染:**
+ * **方案 A (静态图):** `Matplotlib` + `PyGraphviz`。优点是生成速度快,直接发送图片文件到群聊。
+ * **方案 B (动态/高清):** `Pyvis` 或 `Plotly`。生成 HTML 后通过无头浏览器(Playwright/Selenium)截图发群。
+* **存储:** Redis 或 MongoDB。记录滚动的近 7 天互动数据(建议设置 TTL,只看短期活跃关系)。
+
+## 4. 关键 API 定义示例 (伪代码)
+
+```python
+class SNAGenerator:
+ def __init__(self, group_id):
+ self.G = nx.DiGraph() # 创建有向图
+
+ def add_interaction(self, from_user, to_user, weight=1):
+ """记录一次互动"""
+ if self.G.has_edge(from_user, to_user):
+ self.G[from_user][to_user]['weight'] += weight
+ else:
+ self.G.add_edge(from_user, to_user, weight=weight)
+
+ def generate_report(self):
+ """计算核心指标"""
+ # 计算影响力排名
+ centrality = nx.degree_centrality(self.G)
+ # 计算社区/小圈子
+ communities = nx.community.greedy_modularity_communities(self.G.to_undirected())
+ return centrality, communities
+
+ def draw(self, output_path):
+ """渲染并保存图片"""
+ # 调用绘图逻辑...
+ pass
+```
+
+## 5. 运营整活建议 (Feature List)
+1. **每周社交周报**:每周一早上推送上周的“群势力分布图”。
+2. **CP 鉴定**:指令 `!cp @A @B`,调取两人连线权重,计算“纯真度”或“舔狗指数”。
+3. **社交破冰**:发现孤立节点(潜水员)时,机器人自动建议核心节点去 @ 对方。
+
+---
+
+**Liu Wei 备注:**
+研发在实现时,重点在于 `stats_collector` 数据的实时接入。如果群成员超过 200 人,绘图时需要剔除权值过低的线段,否则会导致“蜘蛛网”现象,降低可读性。
\ No newline at end of file
diff --git a/plugins/value_rank/templates/social_graph.html b/plugins/value_rank/templates/social_graph.html
index b02f239..99d6b77 100644
--- a/plugins/value_rank/templates/social_graph.html
+++ b/plugins/value_rank/templates/social_graph.html
@@ -49,12 +49,15 @@
- 说明:节点越大代表连接群友越多;连线越粗代表互动越强。该图仅基于 @ 关系统计,不含纯文本对话引用关系。
+ 说明:节点越大代表连接群友越多;连线越粗代表互动越强。节点优先显示成员头像,缺失头像时自动回退昵称首字。