Skip to content

Commit 435511d

Browse files
authored
Merge pull request #608 from actiontech/temporary/knowledge-detail
Temporary/knowledge detail
2 parents 62024ea + ca13b2f commit 435511d

36 files changed

+2510
-1058
lines changed

packages/shared/lib/api/sqle/service/knowledge_base/index.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export interface IGetKnowledgeBaseListParams {
1616

1717
export interface IGetKnowledgeBaseListReturn extends IGetKnowledgeBaseListRes {}
1818

19+
export interface IGetKnowledgeGraphParams {
20+
filter_by_rule_name?: string;
21+
}
22+
1923
export interface IGetKnowledgeGraphReturn extends IGetKnowledgeGraphResp {}
2024

2125
export interface IGetKnowledgeBaseTagListReturn

packages/shared/lib/api/sqle/service/knowledge_base/index.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { AxiosRequestConfig } from 'axios';
99
import {
1010
IGetKnowledgeBaseListParams,
1111
IGetKnowledgeBaseListReturn,
12+
IGetKnowledgeGraphParams,
1213
IGetKnowledgeGraphReturn,
1314
IGetKnowledgeBaseTagListReturn
1415
} from './index.d';
@@ -26,10 +27,14 @@ class KnowledgeBaseService extends ServiceBase {
2627
);
2728
}
2829

29-
public getKnowledgeGraph(options?: AxiosRequestConfig) {
30+
public getKnowledgeGraph(
31+
params: IGetKnowledgeGraphParams,
32+
options?: AxiosRequestConfig
33+
) {
34+
const paramsData = this.cloneDeep(params);
3035
return this.get<IGetKnowledgeGraphReturn>(
3136
'/v1/knowledge_bases/graph',
32-
undefined,
37+
paramsData,
3338
options
3439
);
3540
}

packages/shared/lib/testUtil/mockEditor.jsx

+35-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { cloneDeep, isObject } from 'lodash';
22

33
const mockEditor = (props) => {
4-
const { onMount, onChange, value, ...otherProps } = props;
4+
const { onMount, onChange, value, commands, ...otherProps } = props;
55

66
const cloneProps = cloneDeep(otherProps);
77

@@ -10,6 +10,36 @@ const mockEditor = (props) => {
1010
cloneProps[key] = JSON.stringify(cloneProps[key]);
1111
}
1212
});
13+
14+
// @uiw/react-md-editor commands
15+
if (commands) {
16+
return (
17+
<div>
18+
<input
19+
onChange={(e) => onChange(e.target.value)}
20+
value={value ?? ''}
21+
{...cloneProps}
22+
/>
23+
{commands.map((command) => {
24+
return (
25+
<button
26+
key={command.keyCommand}
27+
{...command.buttonProps}
28+
onClick={() =>
29+
command.execute(null, {
30+
replaceSelection: (v) => onChange?.(v)
31+
})
32+
}
33+
>
34+
{command.name}
35+
{command.icon}
36+
</button>
37+
);
38+
})}
39+
</div>
40+
);
41+
}
42+
1343
return (
1444
<input
1545
onChange={(e) => onChange(e.target.value)}
@@ -31,4 +61,8 @@ export const loader = {
3161
init: jest.fn(() => Promise.resolve())
3262
};
3363

64+
export const commands = {
65+
getCommands: () => []
66+
};
67+
3468
export default mockEditor;

packages/sqle/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"iwanthue": "^2.0.0",
1717
"react-grid-layout": "^1.3.4",
1818
"react-infinite-scroll-component": "^6.1.0",
19+
"rehype-rewrite": "^4.0.2",
1920
"rehype-sanitize": "^6.0.0",
2021
"sigma": "^3.0.1",
2122
"use-resize-observer": "^9.0.2",

packages/sqle/src/locale/zh-CN/ruleKnowledge.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ export default {
88
noData: '暂无数据, 请编辑',
99
hasDirtyDataTips: '当前内容已经发生更改,是否确认取消修改?',
1010
successTips: '规则理解修改成功',
11-
editorPlaceholder: '在此处输入..'
11+
editorPlaceholder: '在此处输入..',
12+
knowledgeGraph: '关联的语法节点',
13+
originalSql: '原始SQL',
14+
optimizedSql: '优化SQL'
1215
};

packages/sqle/src/page/Knowledge/Graph/components/NodePopover.tsx

+57-38
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,28 @@ const NodePopover: React.FC<NodePopoverProps> = ({ nodeId }) => {
4040
}
4141

4242
clearHideTimeout();
43-
setIsPositionReady(false); // 重置位置状态
43+
// 避免不必要的状态重置,只在真正需要时设置
44+
if (visible) {
45+
setIsPositionReady(false); // 重置位置状态
46+
}
4447
const node = sigma.getGraph().getNodeAttributes(nodeId);
4548
const displayData = sigma.getNodeDisplayData(nodeId);
4649

4750
if (node && displayData) {
4851
const containerRect = sigma.getContainer().getBoundingClientRect();
4952
const viewportPos = sigma.framedGraphToViewport(displayData);
5053

51-
// 考虑左侧菜单栏和顶部区域的偏移
52-
const MENU_WIDTH = 270;
53-
const HEADER_HEIGHT = 156;
54-
54+
// 直接使用容器相对位置,不再硬编码菜单和头部偏移 这样更灵活,适应不同布局情况
5555
const finalPosition = {
56-
x: containerRect.left + viewportPos.x - MENU_WIDTH,
57-
y: containerRect.top + viewportPos.y - HEADER_HEIGHT + window.scrollY
56+
x: viewportPos.x,
57+
y: viewportPos.y
5858
};
5959

6060
// 调整 Popover 位置,考虑节点大小
61-
const nodeSize = displayData.size;
62-
finalPosition.y -= nodeSize + 20;
61+
const nodeSize = displayData.size || 5;
62+
63+
// 将弹出框定位在节点上方,距离为节点大小的 1.5 倍
64+
finalPosition.y -= nodeSize * 1.5;
6365

6466
// 确保不超出图谱容器边界
6567
const graphWidth = containerRect.width;
@@ -75,9 +77,13 @@ const NodePopover: React.FC<NodePopoverProps> = ({ nodeId }) => {
7577
}
7678

7779
if (finalPosition.y < 0) {
78-
finalPosition.y = nodeSize + 20; // 如果超出顶部,显示在节点下方
79-
} else if (finalPosition.y + POPOVER_HEIGHT > graphHeight) {
80-
finalPosition.y = graphHeight - POPOVER_HEIGHT;
80+
// 如果上方放不下,则放在节点下方
81+
finalPosition.y = viewportPos.y + nodeSize * 1.5;
82+
83+
// 如果下方也放不下,则尽量靠近顶部但不超出
84+
if (finalPosition.y + POPOVER_HEIGHT > graphHeight) {
85+
finalPosition.y = Math.min(5, graphHeight - POPOVER_HEIGHT);
86+
}
8187
}
8288

8389
setPosition(finalPosition);
@@ -89,7 +95,7 @@ const NodePopover: React.FC<NodePopoverProps> = ({ nodeId }) => {
8995
setVisible(true);
9096
});
9197
}
92-
}, [nodeId, sigma, hidePopover, clearHideTimeout]);
98+
}, [nodeId, sigma, hidePopover, clearHideTimeout, visible]);
9399

94100
useEffect(() => {
95101
if (!nodeId) {
@@ -99,7 +105,7 @@ const NodePopover: React.FC<NodePopoverProps> = ({ nodeId }) => {
99105
clearHideTimeout();
100106
// 使用防抖处理位置更新
101107
const createDebouncedUpdate = (updateFn: () => void) =>
102-
debounce(updateFn, 16, { leading: true, trailing: true });
108+
debounce(updateFn, 50, { leading: true, trailing: true });
103109

104110
const debouncedUpdatePosition = createDebouncedUpdate(updatePosition);
105111

@@ -123,34 +129,47 @@ const NodePopover: React.FC<NodePopoverProps> = ({ nodeId }) => {
123129

124130
return (
125131
<div
132+
className="node-popover-container"
126133
style={{
127134
position: 'absolute',
128-
left: `${position.x}px`,
129-
top: `${position.y}px`,
130-
transform: 'translate(-50%, -100%)',
131-
pointerEvents: 'auto',
132-
zIndex: 1000,
133-
opacity: isPositionReady ? 1 : 0,
134-
transition: 'opacity 0.2s'
135+
left: 0,
136+
top: 0,
137+
width: '100%',
138+
height: '100%',
139+
pointerEvents: 'none',
140+
zIndex: 1000
135141
}}
136-
onMouseEnter={clearHideTimeout}
137-
onMouseLeave={hidePopover}
138142
>
139-
<Popover
140-
open={visible}
141-
content={
142-
<Typography.Link
143-
href={parse2ReactRouterPath(ROUTE_PATHS.SQLE.KNOWLEDGE.refined, {
144-
queries: {
145-
tags: nodeData.label
146-
}
147-
})}
148-
target="__blank"
149-
>
150-
{t('knowledgeBase.graph.viewRelatedRules')}
151-
</Typography.Link>
152-
}
153-
/>
143+
<div
144+
className="node-popover-content"
145+
style={{
146+
position: 'absolute',
147+
left: `${position.x}px`,
148+
top: `${position.y}px`,
149+
transform: 'translate(-50%, -50%)',
150+
pointerEvents: 'auto',
151+
opacity: 1,
152+
transition: 'opacity 0.2s'
153+
}}
154+
onMouseEnter={clearHideTimeout}
155+
onMouseLeave={hidePopover}
156+
>
157+
<Popover
158+
open={true}
159+
content={
160+
<Typography.Link
161+
href={parse2ReactRouterPath(ROUTE_PATHS.SQLE.KNOWLEDGE.refined, {
162+
queries: {
163+
tags: nodeData.label
164+
}
165+
})}
166+
target="__blank"
167+
>
168+
{t('knowledgeBase.graph.viewRelatedRules')}
169+
</Typography.Link>
170+
}
171+
/>
172+
</div>
154173
</div>
155174
);
156175
};

packages/sqle/src/page/Knowledge/index.ee.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const KnowledgeEE: React.FC = () => {
2121
};
2222

2323
const { data: graphData } = useRequest(() =>
24-
KnowledgeBaseService.getKnowledgeGraph().then((res) => {
24+
KnowledgeBaseService.getKnowledgeGraph({}).then((res) => {
2525
if (res.data.code === ResponseCode.SUCCESS) {
2626
return {
2727
edges: res.data.data?.edges ?? [],

0 commit comments

Comments
 (0)