优化参数表样式与科学计数法支持
This commit is contained in:
1 parent
046aa49814
commit
32f21f08ff
6 files changed
+547
-64
No files matched your search
+145
-26
@@ -100,6 +100,7 @@ import {
|
||||
import {
|
||||
evaluateParameterExpression,
|
||||
isParameterExpressionValue,
|
||||
isScientificNotationValue,
|
||||
} from "./parameterExpression";
|
||||
import {
|
||||
WorkspaceViewTabs,
|
||||
@@ -108,6 +109,10 @@ import {
|
||||
|
||||
type ParameterValue = number | string;
|
||||
type UnitQuantity = string;
|
||||
type ParameterScientificNotation = {
|
||||
text: string;
|
||||
unit: string;
|
||||
};
|
||||
type PortKind = "physical" | "signal";
|
||||
type PortNominalRole = "inlet" | "outlet" | "bidirectional" | "input" | "output";
|
||||
type PortSide = "left" | "right";
|
||||
@@ -255,6 +260,7 @@ type SimulationNodeData = {
|
||||
ports: PortDefinition[];
|
||||
parameters: Record<string, ParameterValue>;
|
||||
parameterUnits: Record<string, string>;
|
||||
parameterScientificNotation: Record<string, ParameterScientificNotation>;
|
||||
rotation: NodeRotation;
|
||||
mirrored: boolean;
|
||||
portConnectionStates?: Record<string, PortConnectionState>;
|
||||
@@ -288,8 +294,12 @@ type ProjectNodePayload = {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
data: Omit<SimulationNodeData, "parameterUnits"> & {
|
||||
data: Omit<
|
||||
SimulationNodeData,
|
||||
"parameterUnits" | "parameterScientificNotation"
|
||||
> & {
|
||||
parameterUnits?: Record<string, string>;
|
||||
parameterScientificNotation?: Record<string, ParameterScientificNotation>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1199,6 +1209,7 @@ function buildNodeData(definition: ComponentDefinition): SimulationNodeData {
|
||||
ports: definition.ports.map((port) => ({ ...port })),
|
||||
parameters: defaultParameters(definition),
|
||||
parameterUnits: defaultParameterUnits(definition),
|
||||
parameterScientificNotation: {},
|
||||
rotation: 0,
|
||||
mirrored: false,
|
||||
};
|
||||
@@ -2709,6 +2720,7 @@ function DeferredNumberInput({
|
||||
<input
|
||||
aria-invalid={invalid}
|
||||
aria-label={ariaLabel}
|
||||
className="parameter-number-input"
|
||||
inputMode="text"
|
||||
onBlur={() => {
|
||||
editingRef.current = false;
|
||||
@@ -3971,34 +3983,62 @@ function FlowWorkbench() {
|
||||
const unit = findUnitOption(definition, selectedUnit);
|
||||
const normalizedDisplayValue = displayValue.trim();
|
||||
const numericValue = Number(normalizedDisplayValue);
|
||||
const baseValue =
|
||||
normalizedDisplayValue === "" || !Number.isFinite(numericValue)
|
||||
? normalizedDisplayValue
|
||||
: unit.toBase(numericValue);
|
||||
const hasFiniteNumericValue =
|
||||
normalizedDisplayValue !== "" && Number.isFinite(numericValue);
|
||||
const convertedBaseValue = hasFiniteNumericValue
|
||||
? unit.toBase(numericValue)
|
||||
: numericValue;
|
||||
const baseValue = hasFiniteNumericValue
|
||||
? convertedBaseValue
|
||||
: normalizedDisplayValue;
|
||||
const scientificNotation =
|
||||
hasFiniteNumericValue &&
|
||||
Number.isFinite(convertedBaseValue) &&
|
||||
isScientificNotationValue(normalizedDisplayValue)
|
||||
? { text: normalizedDisplayValue, unit: selectedUnit }
|
||||
: null;
|
||||
|
||||
updateSelectedNode((node) => ({
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
parameters: {
|
||||
...node.data.parameters,
|
||||
[key]: baseValue,
|
||||
updateSelectedNode((node) => {
|
||||
const parameterScientificNotation = {
|
||||
...node.data.parameterScientificNotation,
|
||||
};
|
||||
if (scientificNotation) {
|
||||
parameterScientificNotation[key] = scientificNotation;
|
||||
} else {
|
||||
delete parameterScientificNotation[key];
|
||||
}
|
||||
return {
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
parameters: {
|
||||
...node.data.parameters,
|
||||
[key]: baseValue,
|
||||
},
|
||||
parameterScientificNotation,
|
||||
},
|
||||
},
|
||||
}));
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const updateSelectedChoice = (key: string, value: number) => {
|
||||
updateSelectedNode((node) => ({
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
parameters: {
|
||||
...node.data.parameters,
|
||||
[key]: value,
|
||||
updateSelectedNode((node) => {
|
||||
const parameterScientificNotation = {
|
||||
...node.data.parameterScientificNotation,
|
||||
};
|
||||
delete parameterScientificNotation[key];
|
||||
return {
|
||||
...node,
|
||||
data: {
|
||||
...node.data,
|
||||
parameters: {
|
||||
...node.data.parameters,
|
||||
[key]: value,
|
||||
},
|
||||
parameterScientificNotation,
|
||||
},
|
||||
},
|
||||
}));
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const updateSelectedParameterUnit = (key: string, unit: string) => {
|
||||
@@ -4181,7 +4221,9 @@ function FlowWorkbench() {
|
||||
key === "method"
|
||||
? value
|
||||
: normalizedValue !== "" && Number.isFinite(numericValue)
|
||||
? numericValue
|
||||
? isScientificNotationValue(normalizedValue)
|
||||
? normalizedValue
|
||||
: numericValue
|
||||
: normalizedValue,
|
||||
}));
|
||||
};
|
||||
@@ -4961,6 +5003,7 @@ function FlowWorkbench() {
|
||||
baseValue,
|
||||
definition,
|
||||
selectedUnit,
|
||||
selectedNode.data.parameterScientificNotation[key],
|
||||
);
|
||||
const mediumDefinitionIndex =
|
||||
isAmesimGasMediumDefinition(selectedDefinition) && key === "gi";
|
||||
@@ -5249,7 +5292,7 @@ function FlowWorkbench() {
|
||||
];
|
||||
const parameterTableAvailableWidth = Math.max(
|
||||
0,
|
||||
modelingPaneLayout.propertiesWidth - 24,
|
||||
modelingPaneLayout.propertiesWidth,
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -5900,6 +5943,9 @@ function buildProjectPayload(
|
||||
ports: node.data.ports.map((port) => ({ ...port })),
|
||||
parameters: { ...node.data.parameters },
|
||||
parameterUnits: { ...node.data.parameterUnits },
|
||||
parameterScientificNotation: {
|
||||
...node.data.parameterScientificNotation,
|
||||
},
|
||||
rotation: normalizeNodeRotation(node.data.rotation),
|
||||
mirrored: Boolean(node.data.mirrored),
|
||||
},
|
||||
@@ -5915,6 +5961,33 @@ function buildProjectPayload(
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeParameterScientificNotation(
|
||||
value: unknown,
|
||||
): Record<string, ParameterScientificNotation> {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return {};
|
||||
}
|
||||
const normalized: Record<string, ParameterScientificNotation> = {};
|
||||
Object.entries(value as Record<string, unknown>).forEach(([key, entry]) => {
|
||||
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
||||
return;
|
||||
}
|
||||
const candidate = entry as Record<string, unknown>;
|
||||
if (
|
||||
typeof candidate.text !== "string" ||
|
||||
typeof candidate.unit !== "string" ||
|
||||
!isScientificNotationValue(candidate.text)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
normalized[key] = {
|
||||
text: candidate.text.trim(),
|
||||
unit: candidate.unit,
|
||||
};
|
||||
});
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function normalizeLoadedNode(
|
||||
node: ProjectNodePayload,
|
||||
componentDefinitions: ComponentDefinition[],
|
||||
@@ -5935,6 +6008,9 @@ function normalizeLoadedNode(
|
||||
const parameterUnits = definition
|
||||
? { ...defaultParameterUnits(definition), ...(node.data.parameterUnits ?? {}) }
|
||||
: { ...(node.data.parameterUnits ?? {}) };
|
||||
const parameterScientificNotation = normalizeParameterScientificNotation(
|
||||
node.data.parameterScientificNotation,
|
||||
);
|
||||
|
||||
return {
|
||||
id: node.id,
|
||||
@@ -5953,6 +6029,7 @@ function normalizeLoadedNode(
|
||||
ports: normalizeLoadedPorts(node.data.ports, definition),
|
||||
parameters,
|
||||
parameterUnits,
|
||||
parameterScientificNotation,
|
||||
rotation: normalizeNodeRotation(node.data.rotation),
|
||||
mirrored: Boolean(node.data.mirrored),
|
||||
},
|
||||
@@ -6190,6 +6267,7 @@ function displayParameterValue(
|
||||
baseValue: ParameterValue,
|
||||
definition: ParameterDefinition,
|
||||
selectedUnit: string,
|
||||
scientificNotation?: ParameterScientificNotation,
|
||||
) {
|
||||
if (typeof baseValue === "string" && baseValue.trim() === "") {
|
||||
return "";
|
||||
@@ -6198,7 +6276,16 @@ function displayParameterValue(
|
||||
if (!Number.isFinite(numericValue)) {
|
||||
return String(baseValue);
|
||||
}
|
||||
return formatEditableNumber(findUnitOption(definition, selectedUnit).fromBase(numericValue));
|
||||
const displayValue = findUnitOption(definition, selectedUnit).fromBase(numericValue);
|
||||
if (
|
||||
scientificNotation &&
|
||||
isScientificNotationValue(scientificNotation.text)
|
||||
) {
|
||||
return scientificNotation.unit === selectedUnit
|
||||
? scientificNotation.text.trim()
|
||||
: formatScientificEditableNumber(displayValue, scientificNotation.text);
|
||||
}
|
||||
return formatEditableNumber(displayValue);
|
||||
}
|
||||
|
||||
function formatEditableNumber(value: number) {
|
||||
@@ -6208,6 +6295,38 @@ function formatEditableNumber(value: number) {
|
||||
return Number(value.toPrecision(12)).toString();
|
||||
}
|
||||
|
||||
const SCIENTIFIC_NOTATION_STYLE_PATTERN =
|
||||
/^[+-]?(?:\d+(?:\.(\d*))?|\.(\d+))([eE])([+-]?)(\d+)$/;
|
||||
|
||||
function formatScientificEditableNumber(value: number, notationHint: string) {
|
||||
if (!Number.isFinite(value)) {
|
||||
return "";
|
||||
}
|
||||
const style = SCIENTIFIC_NOTATION_STYLE_PATTERN.exec(notationHint.trim());
|
||||
if (!style) {
|
||||
return Number(value.toPrecision(12)).toExponential();
|
||||
}
|
||||
|
||||
const minimumFractionDigits = (style[1] ?? style[2] ?? "").length;
|
||||
const exponentMarker = style[3];
|
||||
const showPositiveExponentSign = style[4] === "+";
|
||||
const roundedDisplayValue = Number(value.toPrecision(15));
|
||||
const [rawMantissa, rawExponent] = roundedDisplayValue.toExponential().split("e");
|
||||
const [wholePart, rawFraction = ""] = rawMantissa.split(".");
|
||||
let fraction = rawFraction;
|
||||
while (fraction.endsWith("0") && fraction.length > minimumFractionDigits) {
|
||||
fraction = fraction.slice(0, -1);
|
||||
}
|
||||
if (fraction.length < minimumFractionDigits) {
|
||||
fraction = fraction.padEnd(minimumFractionDigits, "0");
|
||||
}
|
||||
|
||||
const exponent = Number(rawExponent);
|
||||
const exponentSign = exponent < 0 ? "-" : showPositiveExponentSign ? "+" : "";
|
||||
const exponentDigits = String(Math.abs(exponent));
|
||||
return `${wholePart}${fraction ? `.${fraction}` : ""}${exponentMarker}${exponentSign}${exponentDigits}`;
|
||||
}
|
||||
|
||||
function parameterMetadataValue(
|
||||
value: ParameterValue,
|
||||
definition: ParameterDefinition,
|
||||
|
||||
Reference in new issue
Block a user