Improve MindSpace visual editor UX and default RMB billing.

Add color-coded edit highlights with an in-preview legend, strip CSP meta
for srcdoc editing, and simplify fullscreen preview to immersive visual edit
only. Default billing to CNY token rates unless H5_USE_BACKEND_COST=1.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
John
2026-06-15 23:47:23 -07:00
parent 8d2f55771c
commit 79457230c1
11 changed files with 339 additions and 225 deletions
@@ -11,7 +11,9 @@ export function MindSpacePageEditablePreviewFrame({
reloadKey,
minHeight = 680,
maxHeight = 12000,
className = 'mindspace-page-preview-frame',
className,
compact = false,
fillViewport = false,
showHint = true,
onContentChange,
}: {
@@ -21,9 +23,14 @@ export function MindSpacePageEditablePreviewFrame({
minHeight?: number;
maxHeight?: number;
className?: string;
compact?: boolean;
fillViewport?: boolean;
showHint?: boolean;
onContentChange: (html: string) => void;
}) {
const scrollInsideFrame = compact || fillViewport;
const frameClassName =
className ?? (compact ? 'page-save-mini-page-frame' : 'mindspace-page-preview-frame');
const [previewFailed, setPreviewFailed] = useState(false);
const [srcdoc, setSrcdoc] = useState(() => buildEditablePreviewDocument(content));
const [height, setHeight] = useState(minHeight);
@@ -62,6 +69,11 @@ export function MindSpacePageEditablePreviewFrame({
}, [onContentChange]);
useEffect(() => {
if (scrollInsideFrame) {
syncHeightRef.current = null;
return;
}
const iframe = iframeRef.current;
if (!iframe || !srcdoc) return;
@@ -85,7 +97,7 @@ export function MindSpacePageEditablePreviewFrame({
syncHeightRef.current = null;
unbind();
};
}, [maxHeight, minHeight, srcdoc]);
}, [maxHeight, minHeight, scrollInsideFrame, srcdoc]);
if (previewFailed) {
return <div className="mindspace-state mindspace-error">页面预览加载失败</div>;
@@ -95,7 +107,14 @@ export function MindSpacePageEditablePreviewFrame({
<>
{showHint ? (
<p className="mindspace-page-editable-hint">
文字直接改 · 图片/音视频点击换 · 背景点空白区 · 链接双击改地址
<span className="mindspace-page-editable-legend-swatch mindspace-page-editable-legend-swatch-text" />
文字
<span className="mindspace-page-editable-legend-swatch mindspace-page-editable-legend-swatch-media" />
图片/媒体
<span className="mindspace-page-editable-legend-swatch mindspace-page-editable-legend-swatch-link" />
链接
<span className="mindspace-page-editable-legend-swatch mindspace-page-editable-legend-swatch-bg" />
背景 — 预览内左上角有完整图例,虚线框即可直接修改
</p>
) : null}
<iframe
@@ -103,9 +122,9 @@ export function MindSpacePageEditablePreviewFrame({
title={`${title || '页面'} 预览`}
srcDoc={srcdoc}
sandbox="allow-same-origin allow-scripts"
scrolling="no"
className={className}
style={{ height: `${height}px` }}
scrolling={scrollInsideFrame ? 'yes' : 'no'}
className={frameClassName}
style={scrollInsideFrame ? { height: '100%' } : { height: `${height}px` }}
onError={() => setPreviewFailed(true)}
/>
</>