mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-06-01 08:06:15 +08:00
### What problem does this PR solve? feat: alter style of ForceGraph #162 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
e37b0d217d
commit
e8b9871fb9
@ -1,25 +1,19 @@
|
|||||||
import { Graph } from '@antv/g6';
|
|
||||||
import { useSize } from 'ahooks';
|
|
||||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
||||||
import { graphData } from './constant';
|
|
||||||
import { Converter, buildNodesAndCombos, isDataExist } from './util';
|
|
||||||
|
|
||||||
import { useFetchKnowledgeGraph } from '@/hooks/chunk-hooks';
|
import { useFetchKnowledgeGraph } from '@/hooks/chunk-hooks';
|
||||||
|
import { ElementDatum, Graph, IElementEvent } from '@antv/g6';
|
||||||
|
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
|
import { buildNodesAndCombos, isDataExist } from './util';
|
||||||
|
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
|
||||||
const converter = new Converter();
|
const TooltipColorMap = {
|
||||||
|
combo: 'red',
|
||||||
const nextData = converter.buildNodesAndCombos(
|
node: 'black',
|
||||||
graphData.nodes,
|
edge: 'blue',
|
||||||
graphData.edges,
|
};
|
||||||
);
|
|
||||||
console.log('🚀 ~ nextData:', nextData);
|
|
||||||
|
|
||||||
const finalData = { ...graphData, ...nextData };
|
|
||||||
|
|
||||||
const ForceGraph = () => {
|
const ForceGraph = () => {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const size = useSize(containerRef);
|
const graphRef = useRef<Graph | null>(null);
|
||||||
const { data } = useFetchKnowledgeGraph();
|
const { data } = useFetchKnowledgeGraph();
|
||||||
|
|
||||||
const nextData = useMemo(() => {
|
const nextData = useMemo(() => {
|
||||||
@ -30,12 +24,12 @@ const ForceGraph = () => {
|
|||||||
}
|
}
|
||||||
return { nodes: [], edges: [] };
|
return { nodes: [], edges: [] };
|
||||||
}, [data]);
|
}, [data]);
|
||||||
console.log('🚀 ~ nextData ~ nextData:', nextData);
|
|
||||||
|
|
||||||
const render = useCallback(() => {
|
const render = useCallback(() => {
|
||||||
const graph = new Graph({
|
const graph = new Graph({
|
||||||
container: containerRef.current!,
|
container: containerRef.current!,
|
||||||
autoFit: 'view',
|
autoFit: 'view',
|
||||||
|
autoResize: true,
|
||||||
behaviors: [
|
behaviors: [
|
||||||
'drag-element',
|
'drag-element',
|
||||||
'drag-canvas',
|
'drag-canvas',
|
||||||
@ -49,16 +43,23 @@ const ForceGraph = () => {
|
|||||||
plugins: [
|
plugins: [
|
||||||
{
|
{
|
||||||
type: 'tooltip',
|
type: 'tooltip',
|
||||||
getContent: (e, items) => {
|
enterable: true,
|
||||||
if (items.every((x) => x?.description)) {
|
getContent: (e: IElementEvent, items: ElementDatum) => {
|
||||||
|
if (Array.isArray(items)) {
|
||||||
let result = ``;
|
let result = ``;
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
result += `<h3>${item?.id}</h3>`;
|
result += `<section style="color:${TooltipColorMap[e['targetType'] as keyof typeof TooltipColorMap]};"><h3>${item?.id}</h3>`;
|
||||||
|
if (item?.entity_type) {
|
||||||
|
result += `<div style="padding-bottom: 6px;"><b>Entity type: </b>${item?.entity_type}</div>`;
|
||||||
|
}
|
||||||
|
if (item?.weight) {
|
||||||
|
result += `<div><b>Weight: </b>${item?.weight}</div>`;
|
||||||
|
}
|
||||||
if (item?.description) {
|
if (item?.description) {
|
||||||
result += `<p>${item?.description}</p>`;
|
result += `<p>${item?.description}</p>`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result + '</section>';
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
@ -68,44 +69,44 @@ const ForceGraph = () => {
|
|||||||
type: 'combo-combined',
|
type: 'combo-combined',
|
||||||
preventOverlap: true,
|
preventOverlap: true,
|
||||||
comboPadding: 1,
|
comboPadding: 1,
|
||||||
spacing: 20,
|
spacing: 100,
|
||||||
},
|
},
|
||||||
node: {
|
node: {
|
||||||
style: {
|
style: {
|
||||||
size: 20,
|
size: 150,
|
||||||
labelText: (d) => d.id,
|
labelText: (d) => d.id,
|
||||||
labelPadding: 30,
|
// labelPadding: 30,
|
||||||
|
labelFontSize: 40,
|
||||||
// labelOffsetX: 20,
|
// labelOffsetX: 20,
|
||||||
// labelOffsetY: 5,
|
labelOffsetY: 20,
|
||||||
labelPlacement: 'center',
|
labelPlacement: 'center',
|
||||||
labelWordWrap: true,
|
labelWordWrap: true,
|
||||||
},
|
},
|
||||||
palette: {
|
palette: {
|
||||||
type: 'group',
|
type: 'group',
|
||||||
field: (d) => d.combo,
|
field: (d) => {
|
||||||
|
return d?.entity_type as string;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// state: {
|
|
||||||
// highlight: {
|
|
||||||
// fill: '#D580FF',
|
|
||||||
// halo: true,
|
|
||||||
// lineWidth: 0,
|
|
||||||
// },
|
|
||||||
// dim: {
|
|
||||||
// fill: '#99ADD1',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
},
|
},
|
||||||
edge: {
|
edge: {
|
||||||
style: (model) => {
|
style: (model) => {
|
||||||
const { size, color } = model.data;
|
const weight: number = Number(model?.weight) || 2;
|
||||||
|
const lineWeight = weight * 4;
|
||||||
return {
|
return {
|
||||||
stroke: color || '#99ADD1',
|
stroke: '#99ADD1',
|
||||||
lineWidth: size || 1,
|
lineWidth: lineWeight > 10 ? 10 : lineWeight,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (graphRef.current) {
|
||||||
|
graphRef.current.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
graphRef.current = graph;
|
||||||
|
|
||||||
graph.setData(nextData);
|
graph.setData(nextData);
|
||||||
|
|
||||||
graph.render();
|
graph.render();
|
||||||
@ -117,7 +118,13 @@ const ForceGraph = () => {
|
|||||||
}
|
}
|
||||||
}, [data, render]);
|
}, [data, render]);
|
||||||
|
|
||||||
return <div ref={containerRef} className={styles.forceContainer} />;
|
return (
|
||||||
|
<div
|
||||||
|
ref={containerRef}
|
||||||
|
className={styles.forceContainer}
|
||||||
|
style={{ width: '100%', height: '80vh' }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ForceGraph;
|
export default ForceGraph;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
.forceContainer {
|
.forceContainer {
|
||||||
width: 100%;
|
:global(.tooltip) {
|
||||||
height: 100%;
|
border-radius: 10px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalContainer {
|
.modalContainer {
|
||||||
width: 90vw;
|
width: 100%;
|
||||||
height: 80vh;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import ForceGraph from './force-graph';
|
import ForceGraph from './force-graph';
|
||||||
|
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
import { isDataExist } from './util';
|
||||||
|
|
||||||
const KnowledgeGraphModal: React.FC = () => {
|
const KnowledgeGraphModal: React.FC = () => {
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
@ -18,8 +19,7 @@ const KnowledgeGraphModal: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data?.data && typeof data?.data !== 'boolean') {
|
if (isDataExist(data)) {
|
||||||
console.log('🚀 ~ useEffect ~ data:', data);
|
|
||||||
setIsModalOpen(true);
|
setIsModalOpen(true);
|
||||||
}
|
}
|
||||||
}, [setIsModalOpen, data]);
|
}, [setIsModalOpen, data]);
|
||||||
|
@ -65,9 +65,6 @@ export const buildNodesAndCombos = (nodes: any[]) => {
|
|||||||
if (combo && combos.every((y) => y.id !== combo)) {
|
if (combo && combos.every((y) => y.id !== combo)) {
|
||||||
combos.push({
|
combos.push({
|
||||||
id: combo,
|
id: combo,
|
||||||
data: {
|
|
||||||
label: `Combo ${combo}`,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user