|
|
@@ -511,6 +511,17 @@ function NoteNode({ id, data, sourcePosition, targetPosition }) {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ const handleCardClick = (e) => {
|
|
|
+ // 如果点击的是链接或按钮(或其子元素),不处理(避免双重触发)
|
|
|
+ if (e.target.closest('a') || e.target.closest('button')) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 打开原帖链接
|
|
|
+ if (data.note_url) {
|
|
|
+ window.open(data.note_url, '_blank', 'noopener,noreferrer');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
<div>
|
|
|
<Handle
|
|
|
@@ -519,6 +530,7 @@ function NoteNode({ id, data, sourcePosition, targetPosition }) {
|
|
|
style={{ background: '#ec4899', width: 8, height: 8 }}
|
|
|
/>
|
|
|
<div
|
|
|
+ onClick={handleCardClick}
|
|
|
style={{
|
|
|
padding: '14px',
|
|
|
borderRadius: '20px',
|
|
|
@@ -715,7 +727,8 @@ function NoteNode({ id, data, sourcePosition, targetPosition }) {
|
|
|
alt={\`Image \${currentImageIndex + 1}\`}
|
|
|
style={{
|
|
|
width: '100%',
|
|
|
- height: '160px',
|
|
|
+ aspectRatio: '2/3',
|
|
|
+ height: 'auto',
|
|
|
objectFit: 'cover',
|
|
|
display: 'block',
|
|
|
}}
|
|
|
@@ -921,10 +934,22 @@ function AnalysisNode({ data }) {
|
|
|
maxWidth: '900px',
|
|
|
fontSize: '12px',
|
|
|
boxShadow: '0 4px 6px rgba(0,0,0,0.1)',
|
|
|
+ cursor: 'pointer',
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleCardClick = (e) => {
|
|
|
+ // 如果点击的是链接或按钮(或其子元素),不处理(避免双重触发)
|
|
|
+ if (e.target.closest('a') || e.target.closest('button')) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 打开原帖链接
|
|
|
+ if (data.note_url) {
|
|
|
+ window.open(data.note_url, '_blank', 'noopener,noreferrer');
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
- <div style={nodeStyle}>
|
|
|
+ <div style={nodeStyle} onClick={handleCardClick}>
|
|
|
<Handle
|
|
|
type="target"
|
|
|
position={Position.Left}
|
|
|
@@ -1496,8 +1521,8 @@ function getLayoutedElements(nodes, edges, direction = 'LR') {
|
|
|
const isHorizontal = direction === 'LR';
|
|
|
dagreGraph.setGraph({
|
|
|
rankdir: direction,
|
|
|
- nodesep: 180, // 垂直间距 - 增加以避免节点重叠
|
|
|
- ranksep: 360, // 水平间距 - 增加以容纳更宽的节点
|
|
|
+ nodesep: 250, // 垂直间距 - 增加以适应更高的note节点
|
|
|
+ ranksep: 400, // 水平间距 - 增加以容纳更宽的节点
|
|
|
});
|
|
|
|
|
|
// 添加节点 - 根据节点类型设置不同的尺寸
|
|
|
@@ -1508,7 +1533,7 @@ function getLayoutedElements(nodes, edges, direction = 'LR') {
|
|
|
// note 节点有轮播图,需要更大的空间
|
|
|
if (node.type === 'note') {
|
|
|
nodeWidth = 360;
|
|
|
- nodeHeight = 380; // 增加高度以容纳轮播图
|
|
|
+ nodeHeight = 550; // 更新以适应 2:3 比例的轮播图(约450px)+ 其他内容
|
|
|
}
|
|
|
// analysis 节点内容很多,需要更大的空间
|
|
|
else if (node.type === 'analysis') {
|
|
|
@@ -1545,7 +1570,7 @@ function getLayoutedElements(nodes, edges, direction = 'LR') {
|
|
|
let nodeHeight = 220;
|
|
|
if (node.type === 'note') {
|
|
|
nodeWidth = 360;
|
|
|
- nodeHeight = 380;
|
|
|
+ nodeHeight = 550;
|
|
|
}
|
|
|
|
|
|
// 将 dagre 的中心点位置转换为 React Flow 的左上角位置
|
|
|
@@ -1555,6 +1580,54 @@ function getLayoutedElements(nodes, edges, direction = 'LR') {
|
|
|
};
|
|
|
});
|
|
|
|
|
|
+ // 为同层级的 note 节点添加交错偏移,避免视觉重叠
|
|
|
+ console.log('=== 开始交错偏移逻辑 ===');
|
|
|
+ console.log('总节点数:', nodes.length);
|
|
|
+
|
|
|
+ const noteNodes = nodes.filter(n => n.type === 'note');
|
|
|
+ console.log('过滤后的 note 节点数:', noteNodes.length);
|
|
|
+
|
|
|
+ if (noteNodes.length > 1) {
|
|
|
+ // 输出排序前的位置
|
|
|
+ console.log('排序前的 note 节点位置:');
|
|
|
+ noteNodes.forEach((n, i) => {
|
|
|
+ console.log(' [' + i + '] ' + n.id.substring(0, 40) + '... | type=' + n.type + ' | pos=(' + n.position.x.toFixed(0) + ', ' + n.position.y.toFixed(0) + ')');
|
|
|
+ });
|
|
|
+
|
|
|
+ // 按 Y 坐标排序
|
|
|
+ noteNodes.sort((a, b) => a.position.y - b.position.y);
|
|
|
+
|
|
|
+ console.log('排序后的 note 节点位置:');
|
|
|
+ noteNodes.forEach((n, i) => {
|
|
|
+ console.log(' [' + i + '] ' + n.id.substring(0, 40) + '... | pos=(' + n.position.x.toFixed(0) + ', ' + n.position.y.toFixed(0) + ')');
|
|
|
+ });
|
|
|
+
|
|
|
+ // 为相邻的 note 节点添加 X 方向的交错
|
|
|
+ let appliedCount = 0;
|
|
|
+ noteNodes.forEach((node, index) => {
|
|
|
+ if (index > 0) {
|
|
|
+ const prevNode = noteNodes[index - 1];
|
|
|
+ const yDistance = node.position.y - prevNode.position.y;
|
|
|
+
|
|
|
+ console.log('检查节点对 [' + (index-1) + '] vs [' + index + ']:');
|
|
|
+ console.log(' Y距离: ' + yDistance.toFixed(0) + 'px');
|
|
|
+
|
|
|
+ // 直接应用偏移,不再判断 Y 距离(因为实际内容高度可能超过预设)
|
|
|
+ // 奇数索引向右偏移,偶数索引向左偏移
|
|
|
+ const offset = (index % 2 === 0) ? -200 : 200;
|
|
|
+ const oldX = node.position.x;
|
|
|
+ node.position.x += offset;
|
|
|
+ appliedCount++;
|
|
|
+ console.log(' ✅ 应用偏移: X ' + oldX.toFixed(0) + ' → ' + node.position.x.toFixed(0) + ' (偏移' + offset + 'px)');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log('总共应用了 ' + appliedCount + ' 次偏移');
|
|
|
+ } else {
|
|
|
+ console.log('note 节点数量 <= 1,不需要交错');
|
|
|
+ }
|
|
|
+ console.log('=== 交错偏移逻辑结束 ===');
|
|
|
+
|
|
|
console.log('✅ Layout completed, sample node:', nodes[0]);
|
|
|
return { nodes, edges };
|
|
|
} catch (error) {
|
|
|
@@ -1618,7 +1691,7 @@ function transformData(data) {
|
|
|
description: node.body_text || node.desc || '',
|
|
|
isSelected: node.is_selected !== undefined ? node.is_selected : true,
|
|
|
imageList: node.image_list || [],
|
|
|
- noteUrl: node.note_url || '',
|
|
|
+ note_url: node.note_url || '',
|
|
|
evaluationReason: node.evaluationReason || node.evaluation_reason || '',
|
|
|
interact_info: node.interact_info || {},
|
|
|
nodeType: nodeType,
|
|
|
@@ -1972,8 +2045,8 @@ function FlowContent() {
|
|
|
|
|
|
dagreGraph.setGraph({
|
|
|
rankdir: 'LR',
|
|
|
- nodesep: 180, // 垂直间距 - 增加以避免节点重叠
|
|
|
- ranksep: 360, // 水平间距 - 增加以容纳更宽的节点
|
|
|
+ nodesep: 250, // 增加垂直间距以适应更高的note节点
|
|
|
+ ranksep: 400, // 增加水平间距
|
|
|
});
|
|
|
|
|
|
visibleNodes.forEach((node) => {
|
|
|
@@ -1983,7 +2056,7 @@ function FlowContent() {
|
|
|
// note 节点有轮播图,需要更大的空间
|
|
|
if (node.type === 'note') {
|
|
|
nodeWidth = 360;
|
|
|
- nodeHeight = 380;
|
|
|
+ nodeHeight = 550; // 更新以适应 2:3 比例的轮播图(约450px)+ 其他内容
|
|
|
}
|
|
|
|
|
|
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
|
|
|
@@ -2003,7 +2076,7 @@ function FlowContent() {
|
|
|
let nodeHeight = 220;
|
|
|
if (node.type === 'note') {
|
|
|
nodeWidth = 360;
|
|
|
- nodeHeight = 380;
|
|
|
+ nodeHeight = 550; // 更新以适应 2:3 比例的轮播图
|
|
|
}
|
|
|
|
|
|
node.position = {
|
|
|
@@ -2015,6 +2088,36 @@ function FlowContent() {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+ // 为同层级的 note 节点添加交错偏移,避免视觉重叠
|
|
|
+ console.log('[DYNAMIC LAYOUT] 开始应用交错偏移');
|
|
|
+ const noteNodesToStagger = visibleNodes.filter(n => n.type === 'note');
|
|
|
+ console.log('[DYNAMIC LAYOUT] note 节点数:', noteNodesToStagger.length);
|
|
|
+
|
|
|
+ if (noteNodesToStagger.length > 1) {
|
|
|
+ // 按 Y 坐标排序
|
|
|
+ noteNodesToStagger.sort((a, b) => a.position.y - b.position.y);
|
|
|
+
|
|
|
+ console.log('[DYNAMIC LAYOUT] 排序后准备应用偏移:');
|
|
|
+ noteNodesToStagger.forEach((n, i) => {
|
|
|
+ console.log(' [' + i + '] ' + n.id.substring(0, 40) + '... | pos=(' + n.position.x.toFixed(0) + ', ' + n.position.y.toFixed(0) + ')');
|
|
|
+ });
|
|
|
+
|
|
|
+ // 为相邻的 note 节点添加 X 方向的交错
|
|
|
+ let appliedCount = 0;
|
|
|
+ noteNodesToStagger.forEach((node, index) => {
|
|
|
+ if (index > 0) {
|
|
|
+ // 奇数索引向右偏移,偶数索引向左偏移
|
|
|
+ const offset = (index % 2 === 0) ? -200 : 200;
|
|
|
+ const oldX = node.position.x;
|
|
|
+ node.position.x += offset;
|
|
|
+ appliedCount++;
|
|
|
+ console.log('[DYNAMIC LAYOUT] ✅ 应用偏移: X ' + oldX.toFixed(0) + ' → ' + node.position.x.toFixed(0) + ' (偏移' + offset + 'px)');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log('[DYNAMIC LAYOUT] 总共应用了 ' + appliedCount + ' 次偏移');
|
|
|
+ }
|
|
|
+
|
|
|
console.log('✅ Dynamic layout recalculated for', visibleNodes.length, 'visible nodes');
|
|
|
} catch (error) {
|
|
|
console.error('❌ Error in dynamic layout:', error);
|