Skip to content

Commit eb81e23

Browse files
xlorneclaude
andcommitted
refactor: 优化脚本说明展示与变量分区
- 将脚本说明从主函数区域迁移到工具栏,点击问号按钮切换显示 - 变量区域拆分为"函数入参"和"绑定参数"两个独立分区 - SectionHeader 支持 extra 插槽用于扩展操作 - 简化 MainFunctionSection,移除冗余的 tooltip 逻辑 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 6124190 commit eb81e23

7 files changed

Lines changed: 223 additions & 148 deletions

File tree

apps/app-pc/src/pages/home.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,18 @@ const HomePage = () => {
3636
console.log('Code changed:', value);
3737
}}
3838
options={{ minHeight: 400, maxHeight: 500 }}
39-
toolbarExtra={<div style={{ marginLeft: 16, color: '#888' }}>这是额外的工具栏内容</div>}
39+
toolbar={[
40+
{
41+
label: '自定义按钮',
42+
title: '这是一个自定义工具栏按钮',
43+
backgroundColor: '#007bff',
44+
hoverBackgroundColor: '#0056b3',
45+
textColor: '#fff',
46+
borderColor: '#007bff',
47+
onClick: () => message.info('点击了自定义按钮'),
48+
},
49+
]}
50+
toolbarExtra={<div style={{ marginLeft: 16, color: '#888' }}>这是自定义的额外的工具栏内容</div>}
4051
/>
4152
</div>
4253
);
Lines changed: 1 addition & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useRef, useCallback, useEffect } from 'react';
1+
import React from 'react';
22
import type { ScriptMetadata } from '../types';
33
import type { ThemeColors } from './theme-colors';
44
import { SectionHeader } from './section-header';
@@ -8,73 +8,7 @@ export interface MainFunctionSectionProps {
88
colors: ThemeColors;
99
}
1010

11-
// ── Tooltip 定位:基于 fixed 坐标,避免被滚动容器裁剪 ──────────
12-
13-
interface TooltipPos {
14-
top: number;
15-
left: number;
16-
maxWidth: number;
17-
maxHeight: number;
18-
}
19-
20-
const TOOLTIP_MARGIN = 6;
21-
const TOOLTIP_MAX_WIDTH = 380;
22-
23-
function calcTooltipPos(
24-
anchorRect: DOMRect,
25-
tooltipEl: HTMLDivElement | null,
26-
): TooltipPos {
27-
const vw = window.innerWidth;
28-
const vh = window.innerHeight;
29-
30-
// 优先显示在 anchor 下方,空间不足时翻到上方
31-
const tooltipH = tooltipEl?.scrollHeight ?? 200;
32-
const spaceBelow = vh - anchorRect.bottom - TOOLTIP_MARGIN;
33-
const spaceAbove = anchorRect.top - TOOLTIP_MARGIN;
34-
const placeBelow = spaceBelow >= Math.min(tooltipH, 260) || spaceBelow >= spaceAbove;
35-
36-
const top = placeBelow
37-
? anchorRect.bottom + TOOLTIP_MARGIN
38-
: Math.max(TOOLTIP_MARGIN, anchorRect.top - tooltipH - TOOLTIP_MARGIN);
39-
40-
// 水平方向:以 anchor 左边为起点,超出右边界则左移
41-
let left = anchorRect.left;
42-
const maxRight = vw - TOOLTIP_MARGIN;
43-
if (left + TOOLTIP_MAX_WIDTH > maxRight) {
44-
left = Math.max(TOOLTIP_MARGIN, maxRight - TOOLTIP_MAX_WIDTH);
45-
}
46-
47-
const maxWidth = Math.min(TOOLTIP_MAX_WIDTH, maxRight - left);
48-
const maxHeight = placeBelow ? spaceBelow - TOOLTIP_MARGIN : spaceAbove - TOOLTIP_MARGIN;
49-
50-
return { top, left, maxWidth, maxHeight: Math.max(maxHeight, 80) };
51-
}
52-
53-
// ── 组件 ──────────────────────────────────────────────────────
54-
5511
export const MainFunctionSection: React.FC<MainFunctionSectionProps> = ({ metadata, colors }) => {
56-
const [showTip, setShowTip] = useState(false);
57-
const [pos, setPos] = useState<TooltipPos | null>(null);
58-
const anchorRef = useRef<HTMLSpanElement>(null);
59-
const tooltipRef = useRef<HTMLDivElement>(null);
60-
61-
const updatePos = useCallback(() => {
62-
if (!anchorRef.current) return;
63-
const rect = anchorRef.current.getBoundingClientRect();
64-
setPos(calcTooltipPos(rect, tooltipRef.current));
65-
}, []);
66-
67-
useEffect(() => {
68-
if (!showTip) return;
69-
updatePos();
70-
window.addEventListener('scroll', updatePos, true);
71-
window.addEventListener('resize', updatePos);
72-
return () => {
73-
window.removeEventListener('scroll', updatePos, true);
74-
window.removeEventListener('resize', updatePos);
75-
};
76-
}, [showTip, updatePos]);
77-
7812
return (
7913
<div>
8014
<SectionHeader colors={colors} label="主函数" />
@@ -86,32 +20,6 @@ export const MainFunctionSection: React.FC<MainFunctionSectionProps> = ({ metada
8620
<span style={{ color: colors.text, fontWeight: 500 }}>
8721
{metadata.mainMethod}
8822
</span>
89-
{metadata.description && (
90-
<span
91-
ref={anchorRef}
92-
style={{ display: 'inline-flex', cursor: 'help', flexShrink: 0 }}
93-
onMouseEnter={() => setShowTip(true)}
94-
onMouseLeave={() => setShowTip(false)}
95-
>
96-
<span
97-
style={{
98-
display: 'inline-flex',
99-
alignItems: 'center',
100-
justifyContent: 'center',
101-
width: 14,
102-
height: 14,
103-
borderRadius: '50%',
104-
border: `1px solid ${colors.textSecondary}`,
105-
color: colors.textSecondary,
106-
fontSize: 10,
107-
lineHeight: 1,
108-
fontWeight: 600,
109-
}}
110-
>
111-
?
112-
</span>
113-
</span>
114-
)}
11523
<span style={{ color: colors.textSecondary, fontSize: 11 }}>
11624
({metadata.requests.map((r) => `${r.name}: ${r.dataType}`).join(', ')})
11725
</span>
@@ -122,37 +30,6 @@ export const MainFunctionSection: React.FC<MainFunctionSectionProps> = ({ metada
12230
)}
12331
</div>
12432
</div>
125-
126-
{/* Tooltip 渲染在 fixed 层,脱离滚动容器 */}
127-
{showTip && pos && metadata.description && (
128-
<div
129-
ref={tooltipRef}
130-
onMouseEnter={() => setShowTip(true)}
131-
onMouseLeave={() => setShowTip(false)}
132-
style={{
133-
position: 'fixed',
134-
top: pos.top,
135-
left: pos.left,
136-
maxWidth: pos.maxWidth,
137-
maxHeight: pos.maxHeight,
138-
overflowY: 'auto',
139-
padding: '8px 12px',
140-
background: colors.headerBg,
141-
border: `1px solid ${colors.border}`,
142-
borderRadius: 6,
143-
color: colors.text,
144-
fontSize: 12,
145-
lineHeight: 1.65,
146-
whiteSpace: 'pre-wrap',
147-
wordBreak: 'break-word',
148-
zIndex: 9999,
149-
boxShadow: '0 4px 16px rgba(0,0,0,0.3)',
150-
pointerEvents: 'auto',
151-
}}
152-
>
153-
{metadata.description}
154-
</div>
155-
)}
15633
</div>
15734
);
15835
};

packages/script-engine/src/components/section-header.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ import type { ThemeColors } from './theme-colors';
44
export interface SectionHeaderProps {
55
colors: ThemeColors;
66
label: string;
7+
/** 标题右侧的额外操作区域(如按钮、图标) */
8+
extra?: React.ReactNode;
79
}
810

9-
export const SectionHeader: React.FC<SectionHeaderProps> = ({ colors, label }) => (
11+
export const SectionHeader: React.FC<SectionHeaderProps> = ({ colors, label, extra }) => (
1012
<div
1113
style={{
14+
display: 'flex',
15+
alignItems: 'center',
16+
justifyContent: 'space-between',
1217
padding: '6px 12px 4px',
1318
fontSize: 11,
1419
textTransform: 'uppercase',
@@ -17,6 +22,7 @@ export const SectionHeader: React.FC<SectionHeaderProps> = ({ colors, label }) =
1722
fontWeight: 600,
1823
}}
1924
>
20-
{label}
25+
<span>{label}</span>
26+
{extra && <div style={{ display: 'flex', alignItems: 'center' }}>{extra}</div>}
2127
</div>
2228
);

0 commit comments

Comments
 (0)