Skip to content

Commit 22975c8

Browse files
committed
优化链表相交可视化:1. 动态布局计算优化 2. 特殊值处理增强 3. SVG尺寸计算改进 4. 连接线绘制逻辑优化 5. 信息面板自适应优化
1 parent 528009d commit 22975c8

File tree

74 files changed

+4635
-2323
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+4635
-2323
lines changed

src/App.tsx

Lines changed: 51 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,190 +1,88 @@
11
import React, { useEffect } from 'react';
2-
import SolutionCode from './components/SolutionCode';
3-
import D3TwoPointerVisualizer from './components/D3TwoPointerVisualizer';
4-
import LinkedListCreator from './components/LinkedListCreator';
2+
import { TabView, Tab } from './components/TabView';
3+
import Header from './components/layout/Header';
4+
import VisualizationTab from './components/layout/VisualizationTab';
5+
import CodeTab from './components/layout/CodeTab';
56
import ProblemDescription from './components/ProblemDescription';
7+
import LinkedListCreator from './components/LinkedListCreator';
8+
import { useStateManagement } from './hooks/algorithmSteps';
69
import { useAlgorithmSteps } from './hooks/useAlgorithmSteps';
7-
import { TabView, Tab } from './components/TabView';
810

911
const App: React.FC = () => {
12+
const {
13+
showCreator,
14+
setShowCreator
15+
} = useStateManagement();
16+
1017
const {
1118
state,
12-
showCreator,
13-
openCreator,
14-
closeCreator,
1519
createRandomExample,
1620
createCustomExample,
1721
handleStepForward,
1822
handleStepBackward,
1923
handleSpeedChange,
2024
toggleAutoExecution,
21-
resetExecution
25+
resetExecution,
26+
handleChangeSolution
2227
} = useAlgorithmSteps();
2328

24-
// 添加键盘事件监听器
2529
useEffect(() => {
26-
const handleKeyDown = (event: KeyboardEvent) => {
27-
// 确保未在可编辑元素内(如输入框、文本区域等)
28-
if (
29-
document.activeElement?.tagName === 'INPUT' ||
30-
document.activeElement?.tagName === 'TEXTAREA' ||
31-
showCreator // 如果创建器对话框打开,不响应键盘
32-
) {
33-
return;
34-
}
35-
36-
// 左箭头 - 上一步
37-
if (event.key === 'ArrowLeft' && !(state.step === 0 || state.listA.nodes.length === 0)) {
38-
handleStepBackward();
39-
}
40-
// 右箭头 - 下一步
41-
else if (event.key === 'ArrowRight' && !(state.completed || state.listA.nodes.length === 0)) {
42-
handleStepForward();
43-
}
44-
// 空格键 - 暂停/运行
45-
else if (event.key === ' ' && state.listA.nodes.length > 0) {
46-
event.preventDefault(); // 防止页面滚动
47-
toggleAutoExecution();
48-
}
49-
};
30+
console.log('App组件 - showCreator状态变化:', showCreator);
31+
}, [showCreator]);
5032

51-
window.addEventListener('keydown', handleKeyDown);
52-
53-
// 清理函数
54-
return () => {
55-
window.removeEventListener('keydown', handleKeyDown);
56-
};
57-
}, [state.step, state.completed, state.listA.nodes.length, handleStepBackward, handleStepForward, toggleAutoExecution, showCreator, state.isRunning]);
33+
console.log('App组件渲染 - showCreator状态值:', showCreator);
5834

5935
return (
6036
<div className="app-container">
61-
<header className="app-header">
62-
<h1>
63-
<a href="https://leetcode.cn/problems/intersection-of-two-linked-lists/description/"
64-
target="_blank"
65-
rel="noopener noreferrer"
66-
className="title-link">
67-
LeetCode 160: 相交链表
68-
</a>
69-
</h1>
70-
<a
71-
href="https://github.com/fuck-algorithm/leetcode-160-intersection-of-two-linked-lists"
72-
target="_blank"
73-
rel="noopener noreferrer"
74-
className="github-link"
75-
title="View on GitHub"
76-
>
77-
<svg
78-
xmlns="http://www.w3.org/2000/svg"
79-
width="24"
80-
height="24"
81-
viewBox="0 0 24 24"
82-
fill="white"
83-
>
84-
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
85-
</svg>
86-
</a>
87-
</header>
37+
<Header />
8838

89-
<main className="app-content">
39+
<main className="app-content" style={{
40+
minHeight: '80vh',
41+
display: 'flex',
42+
flexDirection: 'column'
43+
}}>
9044
<TabView defaultTab="visualization">
9145
<Tab id="visualization" label="可视化">
92-
<div className="visualization-tab">
93-
<div className="control-panel">
94-
<div className="button-group">
95-
<button className="control-button create" onClick={openCreator}>创建示例</button>
96-
<div className="step-controls">
97-
<button
98-
className="control-button prev"
99-
onClick={handleStepBackward}
100-
disabled={state.step === 0 || state.listA.nodes.length === 0}
101-
title="使用键盘左箭头键(←)也可以执行此操作"
102-
>
103-
<span className="button-text">← 上一步</span>
104-
<span className="keyboard-hint"></span>
105-
</button>
106-
<button
107-
className="control-button step"
108-
onClick={handleStepForward}
109-
disabled={state.completed || state.listA.nodes.length === 0}
110-
title="使用键盘右箭头键(→)也可以执行此操作"
111-
>
112-
<span className="button-text">下一步 →</span>
113-
<span className="keyboard-hint"></span>
114-
</button>
115-
</div>
116-
<button
117-
className="control-button play"
118-
onClick={toggleAutoExecution}
119-
disabled={state.completed || state.listA.nodes.length === 0}
120-
title="使用空格键可以暂停/继续执行"
121-
>
122-
<span className="button-text">{state.isRunning ? '暂停' : '连续执行'}</span>
123-
<span className="keyboard-hint">Space</span>
124-
</button>
125-
<button
126-
className="control-button reset"
127-
onClick={resetExecution}
128-
disabled={state.step === 0 || state.listA.nodes.length === 0}
129-
>
130-
重置
131-
</button>
132-
</div>
133-
134-
<div className="selection-group">
135-
<label htmlFor="speed-control">执行延迟:</label>
136-
<input
137-
id="speed-control"
138-
type="range"
139-
min="100"
140-
max="2000"
141-
step="100"
142-
value={state.speed}
143-
onChange={handleSpeedChange}
144-
disabled={state.isRunning}
145-
className="speed-slider"
146-
title="数值越小执行越快,数值越大执行越慢"
147-
/>
148-
<span className="delay-value">{state.speed}ms</span>
149-
</div>
150-
</div>
151-
<div className="visualization-container">
152-
<D3TwoPointerVisualizer
153-
listA={state.listA}
154-
listB={state.listB}
155-
currentNodeA={state.currentNodeA}
156-
currentNodeB={state.currentNodeB}
157-
intersectionNode={state.intersection}
158-
speed={state.speed}
159-
isRunning={state.isRunning}
160-
message={state.message}
161-
step={state.step}
162-
onAnimationComplete={() => {
163-
// 不需要在这里调用toggleAutoExecution,
164-
// 自动执行逻辑已在useAlgorithmSteps hook的useEffect中处理
165-
// 调用它会导致自动执行在一步后停止
166-
}}
167-
/>
168-
</div>
169-
</div>
46+
<VisualizationTab
47+
state={state}
48+
onOpenCreator={() => {
49+
console.log('App直接设置showCreator为true');
50+
setShowCreator(true);
51+
}}
52+
onStepForward={handleStepForward}
53+
onStepBackward={handleStepBackward}
54+
onSpeedChange={handleSpeedChange}
55+
onToggleExecution={toggleAutoExecution}
56+
onReset={resetExecution}
57+
/>
17058
</Tab>
17159
<Tab id="problem" label="题目描述">
17260
<ProblemDescription />
17361
</Tab>
17462
<Tab id="code" label="算法代码">
175-
<div className="solution-panel full-height">
176-
<h3>双指针解法代码</h3>
177-
<SolutionCode solutionType={state.solutionType} />
178-
</div>
63+
<CodeTab solutionType={state.solutionType} />
17964
</Tab>
18065
</TabView>
18166
</main>
18267

18368
{showCreator && (
18469
<LinkedListCreator
185-
onCreateCustom={createCustomExample}
186-
onCreateRandom={createRandomExample}
187-
onClose={closeCreator}
70+
onCreateCustom={(valuesA, valuesB, intersectionValues) => {
71+
console.log('App调用createCustomExample');
72+
createCustomExample(valuesA, valuesB, intersectionValues);
73+
console.log('App额外调用setShowCreator(false)');
74+
setShowCreator(false);
75+
}}
76+
onCreateRandom={() => {
77+
console.log('App调用createRandomExample');
78+
createRandomExample();
79+
console.log('App额外调用setShowCreator(false)');
80+
setShowCreator(false);
81+
}}
82+
onClose={() => {
83+
console.log('App直接设置showCreator为false');
84+
setShowCreator(false);
85+
}}
18886
/>
18987
)}
19088
</div>

0 commit comments

Comments
 (0)