完善 PNVO001 与 PNRP17 前端图标及端口交互
按 AMESim 参考样式重绘孔板与气动活塞图标,调整端口锚点和旋转后的连接方向,并补充组件图标及接触连接回归测试。
This commit is contained in:
1 parent
1f4027573f
commit
11093613c5
5 files changed
+202
-72
No files matched your search
+18
-2
@@ -1546,7 +1546,7 @@ function transformedPortPlacements(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
port,
|
port,
|
||||||
position: transformedPortPosition(side, rotation, mirrored),
|
position: transformedPortPosition(side, rotation, mirrored, anchor),
|
||||||
x: renderedX,
|
x: renderedX,
|
||||||
y: renderedY,
|
y: renderedY,
|
||||||
};
|
};
|
||||||
@@ -1571,12 +1571,28 @@ function transformedPortPosition(
|
|||||||
side: PortSide,
|
side: PortSide,
|
||||||
rotation: NodeRotation,
|
rotation: NodeRotation,
|
||||||
mirrored: boolean,
|
mirrored: boolean,
|
||||||
|
anchor?: { x: number; y: number },
|
||||||
) {
|
) {
|
||||||
let directionX = side === "left" ? -1 : 1;
|
let directionX = side === "left" ? -1 : 1;
|
||||||
|
let directionY = 0;
|
||||||
|
|
||||||
|
if (anchor) {
|
||||||
|
const closestEdge = [
|
||||||
|
{ distance: anchor.x, x: -1, y: 0 },
|
||||||
|
{ distance: SYMBOL_VIEWBOX_WIDTH - anchor.x, x: 1, y: 0 },
|
||||||
|
{ distance: anchor.y, x: 0, y: -1 },
|
||||||
|
{ distance: SYMBOL_VIEWBOX_HEIGHT - anchor.y, x: 0, y: 1 },
|
||||||
|
].reduce((closest, candidate) =>
|
||||||
|
candidate.distance < closest.distance ? candidate : closest,
|
||||||
|
);
|
||||||
|
directionX = closestEdge.x;
|
||||||
|
directionY = closestEdge.y;
|
||||||
|
}
|
||||||
|
|
||||||
if (mirrored) {
|
if (mirrored) {
|
||||||
directionX = -directionX;
|
directionX = -directionX;
|
||||||
}
|
}
|
||||||
const [x, y] = rotatePoint(directionX, 0, rotation);
|
const [x, y] = rotatePoint(directionX, directionY, rotation);
|
||||||
if (x < -0.01) {
|
if (x < -0.01) {
|
||||||
return Position.Left;
|
return Position.Left;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,15 +263,15 @@ const symbolPortAnchors: Partial<
|
|||||||
right: [{ x: 62, y: 24 }],
|
right: [{ x: 62, y: 24 }],
|
||||||
},
|
},
|
||||||
amesim_pnvo001_fixed: {
|
amesim_pnvo001_fixed: {
|
||||||
left: [{ x: 2, y: 28 }],
|
left: [{ x: 2, y: 24 }],
|
||||||
right: [{ x: 62, y: 28 }],
|
right: [{ x: 62, y: 24 }],
|
||||||
},
|
},
|
||||||
amesim_pnvo001: {
|
amesim_pnvo001: {
|
||||||
left: [
|
left: [
|
||||||
{ x: 2, y: 16 },
|
{ x: 26, y: 46 },
|
||||||
{ x: 2, y: 32 },
|
{ x: 2, y: 24 },
|
||||||
],
|
],
|
||||||
right: [{ x: 62, y: 25 }],
|
right: [{ x: 62, y: 24 }],
|
||||||
},
|
},
|
||||||
amesim_pnl00r: {
|
amesim_pnl00r: {
|
||||||
left: [{ x: 2, y: 24 }],
|
left: [{ x: 2, y: 24 }],
|
||||||
@@ -325,11 +325,11 @@ const symbolPortAnchors: Partial<
|
|||||||
},
|
},
|
||||||
amesim_pnrp17: {
|
amesim_pnrp17: {
|
||||||
left: [
|
left: [
|
||||||
{ x: 2, y: 24 },
|
{ x: 25.5, y: 48 },
|
||||||
{ x: 2, y: 10 },
|
{ x: 2, y: 4.4 },
|
||||||
{ x: 2, y: 38 },
|
{ x: 2, y: 24.1 },
|
||||||
],
|
],
|
||||||
right: [{ x: 62, y: 10 }, { x: 62, y: 38 }],
|
right: [{ x: 62, y: 4.4 }, { x: 62, y: 24.1 }],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import {
|
|||||||
} from "./primitives";
|
} from "./primitives";
|
||||||
|
|
||||||
const MECHANICAL_LINE_WIDTH = 1.8;
|
const MECHANICAL_LINE_WIDTH = 1.8;
|
||||||
|
const PNRP17_STROKE = "#8b134f";
|
||||||
|
const PNRP17_FILL = "#cf9db6";
|
||||||
|
const PNRP17_LIGHT_FILL = "#f5ebf0";
|
||||||
|
|
||||||
const mechanicalStroke = {
|
const mechanicalStroke = {
|
||||||
fill: "none",
|
fill: "none",
|
||||||
@@ -220,50 +223,81 @@ export function AmesimPnrp17Symbol() {
|
|||||||
return (
|
return (
|
||||||
<SymbolSvg className="component-symbol-amesim-pnrp17" domain="mechanical">
|
<SymbolSvg className="component-symbol-amesim-pnrp17" domain="mechanical">
|
||||||
<path
|
<path
|
||||||
d="M2 24h17M2 10h11M2 38h11M51 10h11M51 38h11"
|
d="M13.4 1.1H51.4V3h4.1v2.9h-4.1v1.9H18.2v13.8h-10V7h5.2V5.9H9.3V3h4.1Z"
|
||||||
{...mechanicalStroke}
|
fill={PNRP17_FILL}
|
||||||
/>
|
stroke={PNRP17_STROKE}
|
||||||
<path
|
strokeLinejoin="miter"
|
||||||
d="M7 6v8h6M7 34v8h6M57 6v8h-6M57 34v8h-6"
|
|
||||||
{...mechanicalStroke}
|
|
||||||
/>
|
|
||||||
<rect
|
|
||||||
fill={SYMBOL_FILL}
|
|
||||||
height="34"
|
|
||||||
rx="1"
|
|
||||||
stroke={SYMBOL_STROKE}
|
|
||||||
strokeWidth="2"
|
|
||||||
width="32"
|
|
||||||
x="18"
|
|
||||||
y="7"
|
|
||||||
/>
|
|
||||||
<path d="M38 8v32M38 24h12" {...mechanicalStroke} />
|
|
||||||
<path
|
|
||||||
d="M22 18h12M28 14l6 4-6 4"
|
|
||||||
fill="none"
|
|
||||||
stroke={SYMBOL_ACCENT}
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="1.8"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M4 21v6M7 20v8M10 21v6"
|
|
||||||
fill="none"
|
|
||||||
stroke={SYMBOL_ACCENT}
|
|
||||||
strokeWidth="1.2"
|
strokeWidth="1.2"
|
||||||
/>
|
/>
|
||||||
<text
|
<path
|
||||||
dominantBaseline="central"
|
d="M8.2 26.7h12.7v13.8h2v6.7H8.2Z"
|
||||||
fill={SYMBOL_STROKE}
|
fill={PNRP17_FILL}
|
||||||
fontFamily="Arial, sans-serif"
|
stroke={PNRP17_STROKE}
|
||||||
fontSize="8"
|
strokeLinejoin="miter"
|
||||||
fontWeight="600"
|
strokeWidth="1.2"
|
||||||
textAnchor="middle"
|
/>
|
||||||
x="28"
|
<path
|
||||||
y="32"
|
d="M28 40.5h28.5v6.7H28Z"
|
||||||
>
|
fill={PNRP17_FILL}
|
||||||
P
|
stroke={PNRP17_STROKE}
|
||||||
</text>
|
strokeLinejoin="miter"
|
||||||
|
strokeWidth="1.2"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill={PNRP17_LIGHT_FILL}
|
||||||
|
height="34"
|
||||||
|
stroke={PNRP17_STROKE}
|
||||||
|
strokeWidth="1.2"
|
||||||
|
width="7.7"
|
||||||
|
x="40.8"
|
||||||
|
y="7.2"
|
||||||
|
/>
|
||||||
|
<rect fill={PNRP17_STROKE} height="34" width="1.8" x="38.8" y="7.2" />
|
||||||
|
<rect
|
||||||
|
fill={PNRP17_LIGHT_FILL}
|
||||||
|
height="2.8"
|
||||||
|
stroke={PNRP17_STROKE}
|
||||||
|
strokeWidth="1.2"
|
||||||
|
width="31.5"
|
||||||
|
x="9.3"
|
||||||
|
y="22.7"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
fill={PNRP17_LIGHT_FILL}
|
||||||
|
height="2.8"
|
||||||
|
stroke={PNRP17_STROKE}
|
||||||
|
strokeWidth="1.2"
|
||||||
|
width="7.7"
|
||||||
|
x="47.8"
|
||||||
|
y="22.7"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M2 4.4h7.3m46.2 0H62M2 24.1h7.3m46.2 0H62M25.5 43.4V48"
|
||||||
|
stroke={PNRP17_STROKE}
|
||||||
|
strokeLinecap="butt"
|
||||||
|
strokeWidth="1.2"
|
||||||
|
/>
|
||||||
|
{[15.3, 33].map((centerY) => (
|
||||||
|
<g
|
||||||
|
fill="none"
|
||||||
|
key={centerY}
|
||||||
|
stroke={PNRP17_STROKE}
|
||||||
|
strokeLinecap="butt"
|
||||||
|
strokeLinejoin="miter"
|
||||||
|
strokeWidth="1.1"
|
||||||
|
>
|
||||||
|
<path d={`M28.8 ${centerY}h-3.4`} />
|
||||||
|
<path
|
||||||
|
d={`M25.4 ${centerY - 2.5} 21.5 ${centerY}l3.9 2.5Z`}
|
||||||
|
fill="#ffffff"
|
||||||
|
/>
|
||||||
|
<path d={`M30.9 ${centerY}h3.4`} />
|
||||||
|
<path
|
||||||
|
d={`M34.3 ${centerY - 2.5} 38.3 ${centerY} 34.3 ${centerY + 2.5}Z`}
|
||||||
|
fill="#ffffff"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
))}
|
||||||
</SymbolSvg>
|
</SymbolSvg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from "./primitives";
|
} from "./primitives";
|
||||||
|
|
||||||
const PNEUMATIC_STROKE_WIDTH = 1.7;
|
const PNEUMATIC_STROKE_WIDTH = 1.7;
|
||||||
|
const PNVO001_STROKE = "#8b134f";
|
||||||
|
|
||||||
function OrificeBody({
|
function OrificeBody({
|
||||||
centerY = 25,
|
centerY = 25,
|
||||||
@@ -49,6 +50,46 @@ export function AmesimPnor001Symbol() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Pnvo001Body({
|
||||||
|
signalControlled = false,
|
||||||
|
}: {
|
||||||
|
signalControlled?: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<path
|
||||||
|
d="M0 24.5h64"
|
||||||
|
stroke={PNVO001_STROKE}
|
||||||
|
strokeLinecap="butt"
|
||||||
|
strokeWidth="2.1"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M15.5 14.4Q33.4 27 51.2 14.4M15.5 34.8Q33.2 22.4 51.2 34.8"
|
||||||
|
stroke={PNVO001_STROKE}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="3.1"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M19 46.7 44.5 10"
|
||||||
|
stroke={PNVO001_STROKE}
|
||||||
|
strokeLinecap="butt"
|
||||||
|
strokeWidth="2.6"
|
||||||
|
/>
|
||||||
|
{signalControlled ? (
|
||||||
|
<path
|
||||||
|
d="M26 48V36.6l7.2 10.1"
|
||||||
|
stroke={PNVO001_STROKE}
|
||||||
|
strokeLinecap="butt"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2.3"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<path d="M50.6 0 38.6 8.2 48 12.3Z" fill={PNVO001_STROKE} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** PNVO001 convenience variant whose opening is fixed by a parameter. */
|
/** PNVO001 convenience variant whose opening is fixed by a parameter. */
|
||||||
export function AmesimPnvo001FixedSymbol() {
|
export function AmesimPnvo001FixedSymbol() {
|
||||||
return (
|
return (
|
||||||
@@ -56,14 +97,7 @@ export function AmesimPnvo001FixedSymbol() {
|
|||||||
className="component-symbol-amesim-pnvo001-fixed-svg"
|
className="component-symbol-amesim-pnvo001-fixed-svg"
|
||||||
domain="pneumatic"
|
domain="pneumatic"
|
||||||
>
|
>
|
||||||
<OrificeBody centerY={28} />
|
<Pnvo001Body />
|
||||||
<path
|
|
||||||
d="M43 4 34 20m9-16-2 7-5-3"
|
|
||||||
stroke={SYMBOL_ACCENT}
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="1.7"
|
|
||||||
/>
|
|
||||||
</SymbolSvg>
|
</SymbolSvg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -75,14 +109,7 @@ export function AmesimPnvo001SignalSymbol() {
|
|||||||
className="component-symbol-amesim-pnvo001-signal-svg"
|
className="component-symbol-amesim-pnvo001-signal-svg"
|
||||||
domain="pneumatic"
|
domain="pneumatic"
|
||||||
>
|
>
|
||||||
<OrificeBody centerY={25} leftPortY={32} />
|
<Pnvo001Body signalControlled />
|
||||||
<path
|
|
||||||
d="M2 16h11l21 5m0 0-7-1m7 1-5 5"
|
|
||||||
stroke={SYMBOL_ACCENT}
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="1.7"
|
|
||||||
/>
|
|
||||||
</SymbolSvg>
|
</SymbolSvg>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,22 @@ function signalPort(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mechanicalPort(
|
||||||
|
name: string,
|
||||||
|
side: "left" | "right",
|
||||||
|
order: number,
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
kind: "physical",
|
||||||
|
domain: "mechanical",
|
||||||
|
nominalRole: "bidirectional",
|
||||||
|
positiveFlowDirection: "intoComponent",
|
||||||
|
side,
|
||||||
|
order,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function portsForSymbol(modelType: string) {
|
function portsForSymbol(modelType: string) {
|
||||||
if (modelType === "amesim_pnor001") {
|
if (modelType === "amesim_pnor001") {
|
||||||
return [
|
return [
|
||||||
@@ -80,6 +96,15 @@ function portsForSymbol(modelType: string) {
|
|||||||
if (modelType === "amesim_step0") {
|
if (modelType === "amesim_step0") {
|
||||||
return [signalPort("out", "right", "output", 10)];
|
return [signalPort("out", "right", "output", 10)];
|
||||||
}
|
}
|
||||||
|
if (modelType === "amesim_pnrp17") {
|
||||||
|
return [
|
||||||
|
physicalPort("port_1", "left", 10),
|
||||||
|
mechanicalPort("port_3", "left", 20),
|
||||||
|
mechanicalPort("port_4", "left", 30),
|
||||||
|
mechanicalPort("port_2", "right", 40),
|
||||||
|
mechanicalPort("port_5", "right", 50),
|
||||||
|
];
|
||||||
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,6 +302,33 @@ test("全部已移植 AMESim 模型使用专属图标及正确领域配色", asy
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("PNRP17 图标匹配参考结构并将五个端口放在对应接口", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
|
||||||
|
const paletteSymbol = page.locator(
|
||||||
|
'aside.palette [data-component-symbol="amesim_pnrp17"]',
|
||||||
|
);
|
||||||
|
await expect(paletteSymbol).toHaveCount(1);
|
||||||
|
await expect(
|
||||||
|
paletteSymbol.locator('[stroke="#00af00"], [fill="#00af00"]'),
|
||||||
|
).toHaveCount(0);
|
||||||
|
|
||||||
|
const piston = await dragSymbolToCanvas(page, "amesim_pnrp17", {
|
||||||
|
x: 430,
|
||||||
|
y: 300,
|
||||||
|
});
|
||||||
|
await expectSymbolAnchors(piston, [
|
||||||
|
{ portName: "port_1", x: 25.5, y: 48 },
|
||||||
|
{ portName: "port_3", x: 2, y: 4.4 },
|
||||||
|
{ portName: "port_4", x: 2, y: 24.1 },
|
||||||
|
{ portName: "port_2", x: 62, y: 4.4 },
|
||||||
|
{ portName: "port_5", x: 62, y: 24.1 },
|
||||||
|
]);
|
||||||
|
await expect(
|
||||||
|
piston.locator('.port-handle[data-port-name="port_1"]'),
|
||||||
|
).toHaveClass(/react-flow__handle-bottom/);
|
||||||
|
});
|
||||||
|
|
||||||
test("AMESim canvas nodes use icon anchors and highlight only compatible free ports", async ({
|
test("AMESim canvas nodes use icon anchors and highlight only compatible free ports", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -320,9 +372,9 @@ test("AMESim canvas nodes use icon anchors and highlight only compatible free po
|
|||||||
];
|
];
|
||||||
await expectSymbolAnchors(firstOrifice, firstOrificeAnchors);
|
await expectSymbolAnchors(firstOrifice, firstOrificeAnchors);
|
||||||
await expectSymbolAnchors(signalOrifice, [
|
await expectSymbolAnchors(signalOrifice, [
|
||||||
{ portName: "res", x: 2, y: 16 },
|
{ portName: "res", x: 26, y: 46 },
|
||||||
{ portName: "port_2", x: 2, y: 32 },
|
{ portName: "port_2", x: 2, y: 24 },
|
||||||
{ portName: "port_3", x: 62, y: 25 },
|
{ portName: "port_3", x: 62, y: 24 },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await firstOrifice.locator(".node-symbol").click({ position: { x: 56, y: 42 } });
|
await firstOrifice.locator(".node-symbol").click({ position: { x: 56, y: 42 } });
|
||||||
@@ -350,6 +402,7 @@ test("AMESim canvas nodes use icon anchors and highlight only compatible free po
|
|||||||
const signalInput = signalOrifice.locator(
|
const signalInput = signalOrifice.locator(
|
||||||
'.port-handle[data-port-name="res"]',
|
'.port-handle[data-port-name="res"]',
|
||||||
);
|
);
|
||||||
|
await expect(signalInput).toHaveClass(/react-flow__handle-bottom/);
|
||||||
const pneumaticInput = signalOrifice.locator(
|
const pneumaticInput = signalOrifice.locator(
|
||||||
'.port-handle[data-port-name="port_2"]',
|
'.port-handle[data-port-name="port_2"]',
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in new issue
Block a user