@arronqzy/react-view 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/styles.css +4 -4
- package/package.json +6 -6
- package/src/panel/ReactViewOnlinePreview.tsx +41 -18
- package/src/panel/ReactViewPanel.tsx +52 -2
- package/src/panel/ai/AssistantChatPanel.tsx +15 -41
- package/src/panel/components/PanelConfigSidebar.tsx +442 -352
- package/src/panel/components/WorkspaceConfigSidebar.tsx +8 -0
- package/src/panel/utils/chartOptionBuilder.ts +48 -3
- package/src/panel/utils/outputScale.ts +69 -0
- package/src/panel/utils/panelElementDefaults.ts +0 -1
|
@@ -4,6 +4,7 @@ import { useI18n } from "@arronqzy/i18n/react";
|
|
|
4
4
|
import {
|
|
5
5
|
BlueprintExecutionLogPanel,
|
|
6
6
|
BlueprintNodeConfigSidebar,
|
|
7
|
+
type BlueprintGraphEdge,
|
|
7
8
|
type BlueprintGraphNode,
|
|
8
9
|
type ExecutionLogSettings,
|
|
9
10
|
type ExecutionTraceEntry,
|
|
@@ -41,6 +42,8 @@ export type WorkspaceConfigSidebarProps = Omit<
|
|
|
41
42
|
configFocus: WorkspaceConfigFocus;
|
|
42
43
|
executionLog?: BlueprintExecutionLogViewProps;
|
|
43
44
|
selectedBlueprintNode: BlueprintGraphNode | null;
|
|
45
|
+
blueprintGraphNodes?: BlueprintGraphNode[];
|
|
46
|
+
blueprintGraphEdges?: BlueprintGraphEdge[];
|
|
44
47
|
allowFalseSignalPropagation?: boolean;
|
|
45
48
|
onUpdateAllowFalseSignalPropagation?: (value: boolean) => void;
|
|
46
49
|
onUpdateBlueprintNode: (
|
|
@@ -74,6 +77,8 @@ export function WorkspaceConfigSidebar({
|
|
|
74
77
|
configFocus,
|
|
75
78
|
executionLog,
|
|
76
79
|
selectedBlueprintNode,
|
|
80
|
+
blueprintGraphNodes = [],
|
|
81
|
+
blueprintGraphEdges = [],
|
|
77
82
|
allowFalseSignalPropagation = false,
|
|
78
83
|
onUpdateAllowFalseSignalPropagation,
|
|
79
84
|
onUpdateBlueprintNode,
|
|
@@ -151,6 +156,9 @@ export function WorkspaceConfigSidebar({
|
|
|
151
156
|
return (
|
|
152
157
|
<BlueprintNodeConfigSidebar
|
|
153
158
|
node={selectedBlueprintNode}
|
|
159
|
+
graphNodes={blueprintGraphNodes}
|
|
160
|
+
graphEdges={blueprintGraphEdges}
|
|
161
|
+
traceEntries={executionLog?.entries}
|
|
154
162
|
allowFalseSignalPropagation={allowFalseSignalPropagation}
|
|
155
163
|
onUpdateAllowFalseSignalPropagation={onUpdateAllowFalseSignalPropagation}
|
|
156
164
|
viewElementOptions={viewElementOptions}
|
|
@@ -84,6 +84,45 @@ function deepMerge<T extends Record<string, any>>(base: T, patch?: Record<string
|
|
|
84
84
|
return next as T;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
function resolveBarWidth(chart?: PanelChartConfig): number | undefined {
|
|
88
|
+
const width = chart?.barWidth;
|
|
89
|
+
return typeof width === "number" && Number.isFinite(width) && width > 0 ? width : undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function mixHex(a: string, b: string, t: number): string {
|
|
93
|
+
const pa = parseHex(a);
|
|
94
|
+
const pb = parseHex(b);
|
|
95
|
+
if (!pa || !pb) return a;
|
|
96
|
+
const m = (i: number) => Math.round(pa[i]! * (1 - t) + pb[i]! * t);
|
|
97
|
+
return `#${[m(0), m(1), m(2)].map((n) => n.toString(16).padStart(2, "0")).join("")}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function parseHex(hex: string): [number, number, number] | null {
|
|
101
|
+
const s = hex.replace("#", "").trim();
|
|
102
|
+
const full =
|
|
103
|
+
s.length === 3
|
|
104
|
+
? s
|
|
105
|
+
.split("")
|
|
106
|
+
.map((c) => c + c)
|
|
107
|
+
.join("")
|
|
108
|
+
: s.slice(0, 6);
|
|
109
|
+
if (!/^[0-9a-fA-F]{6}$/.test(full)) return null;
|
|
110
|
+
return [
|
|
111
|
+
Number.parseInt(full.slice(0, 2), 16),
|
|
112
|
+
Number.parseInt(full.slice(2, 4), 16),
|
|
113
|
+
Number.parseInt(full.slice(4, 6), 16),
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function pieSliceColors(base: string, count: number): string[] {
|
|
118
|
+
const n = Math.max(count, 1);
|
|
119
|
+
if (n === 1) return [base];
|
|
120
|
+
return Array.from({ length: n }, (_, i) => {
|
|
121
|
+
const t = n === 1 ? 0 : i / (n - 1);
|
|
122
|
+
return mixHex(mixHex(base, "#111827", 0.12), "#fefce8", t * 0.45);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
87
126
|
export function buildChartOption(element: PanelElement): EChartsOption {
|
|
88
127
|
const chartType = (element.materialType ?? "") as ChartType;
|
|
89
128
|
const labels = resolveChartLabels(element);
|
|
@@ -144,10 +183,11 @@ export function buildChartOption(element: PanelElement): EChartsOption {
|
|
|
144
183
|
if (chartType === "pie") {
|
|
145
184
|
const inner = element.chart?.pieInnerRadius ?? 30;
|
|
146
185
|
const outer = element.chart?.pieOuterRadius ?? 65;
|
|
186
|
+
const sliceColors = pieSliceColors(color, labels.length);
|
|
147
187
|
const baseOption: EChartsOption = {
|
|
148
188
|
animation: false,
|
|
149
189
|
title: { text: title, left: "center", top: 6, textStyle: { fontSize: 12 } },
|
|
150
|
-
color:
|
|
190
|
+
color: sliceColors as any,
|
|
151
191
|
tooltip: tooltipOption,
|
|
152
192
|
series: [
|
|
153
193
|
{
|
|
@@ -155,7 +195,11 @@ export function buildChartOption(element: PanelElement): EChartsOption {
|
|
|
155
195
|
radius: [`${inner}%`, `${outer}%`],
|
|
156
196
|
center: ["50%", "58%"],
|
|
157
197
|
label: { fontSize: 10 },
|
|
158
|
-
data: labels.map((name, i) => ({
|
|
198
|
+
data: labels.map((name, i) => ({
|
|
199
|
+
name,
|
|
200
|
+
value: values[i] ?? 0,
|
|
201
|
+
itemStyle: { color: sliceColors[i % sliceColors.length] as any },
|
|
202
|
+
})),
|
|
159
203
|
},
|
|
160
204
|
],
|
|
161
205
|
};
|
|
@@ -315,7 +359,8 @@ export function buildChartOption(element: PanelElement): EChartsOption {
|
|
|
315
359
|
chartType === "line" || chartType === "area"
|
|
316
360
|
? (element.chart?.smooth ?? true)
|
|
317
361
|
: undefined,
|
|
318
|
-
barWidth:
|
|
362
|
+
barWidth:
|
|
363
|
+
chartType === "bar" ? resolveBarWidth(element.chart) : undefined,
|
|
319
364
|
areaStyle: chartType === "area" ? { opacity: 0.25 } : undefined,
|
|
320
365
|
itemStyle: { color: chartColor as any },
|
|
321
366
|
lineStyle: { color: chartColor as any },
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** 产物预览是否缩放内部内容(字体等)。默认 false:块仍按视口撑满,内容保持原尺寸以免失真。 */
|
|
2
|
+
export const OUTPUT_SCALE_STORAGE_KEY = "panel:outputScale";
|
|
3
|
+
|
|
4
|
+
export function readOutputScale(): boolean {
|
|
5
|
+
try {
|
|
6
|
+
return localStorage.getItem(OUTPUT_SCALE_STORAGE_KEY) === "1";
|
|
7
|
+
} catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function writeOutputScale(enabled: boolean) {
|
|
13
|
+
try {
|
|
14
|
+
localStorage.setItem(OUTPUT_SCALE_STORAGE_KEY, enabled ? "1" : "0");
|
|
15
|
+
} catch {
|
|
16
|
+
// ignore storage errors
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type PreviewFillScale = {
|
|
21
|
+
vw: number;
|
|
22
|
+
vh: number;
|
|
23
|
+
scaleX: number;
|
|
24
|
+
scaleY: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function getPreviewFillScale(
|
|
28
|
+
sceneWidth: number,
|
|
29
|
+
sceneHeight: number
|
|
30
|
+
): PreviewFillScale {
|
|
31
|
+
const vw = window.innerWidth || 1;
|
|
32
|
+
const vh = window.innerHeight || 1;
|
|
33
|
+
const sw = Math.max(1, sceneWidth);
|
|
34
|
+
const sh = Math.max(1, sceneHeight);
|
|
35
|
+
return {
|
|
36
|
+
vw,
|
|
37
|
+
vh,
|
|
38
|
+
scaleX: vw / sw,
|
|
39
|
+
scaleY: vh / sh,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 预览始终按视口宽高比把场景块撑满。
|
|
45
|
+
* outputScale=true:CSS transform 缩放整棵内容(含字体)。
|
|
46
|
+
* outputScale=false:只把场景盒拉到视口大小,节点几何由调用方按 scale 映射,字体不跟着拉伸。
|
|
47
|
+
*/
|
|
48
|
+
export function applyPreviewSceneFill(
|
|
49
|
+
scene: HTMLElement | null,
|
|
50
|
+
sceneWidth: number,
|
|
51
|
+
sceneHeight: number,
|
|
52
|
+
outputScale: boolean
|
|
53
|
+
): PreviewFillScale {
|
|
54
|
+
const fill = getPreviewFillScale(sceneWidth, sceneHeight);
|
|
55
|
+
if (!Number.isFinite(fill.scaleX) || !Number.isFinite(fill.scaleY)) return fill;
|
|
56
|
+
if (!scene) return fill;
|
|
57
|
+
const root = scene.parentElement;
|
|
58
|
+
if (root) root.style.overflow = "hidden";
|
|
59
|
+
if (outputScale) {
|
|
60
|
+
scene.style.width = `${Math.max(1, sceneWidth)}px`;
|
|
61
|
+
scene.style.height = `${Math.max(1, sceneHeight)}px`;
|
|
62
|
+
scene.style.transform = `translate(0px,0px) scale(${fill.scaleX},${fill.scaleY})`;
|
|
63
|
+
} else {
|
|
64
|
+
scene.style.width = `${fill.vw}px`;
|
|
65
|
+
scene.style.height = `${fill.vh}px`;
|
|
66
|
+
scene.style.transform = "none";
|
|
67
|
+
}
|
|
68
|
+
return fill;
|
|
69
|
+
}
|