Commit e3663aab authored by fenghen777's avatar fenghen777

feat: Implement core diagram editor functionality including a component...

feat: Implement core diagram editor functionality including a component library, React Flow state management, and property editing.
parent 5ef2e19f
......@@ -383,8 +383,7 @@
background: #1a1a28;
}
.portTypeSelect,
.portSideSelect {
.portTypeSelect {
width: 52px;
padding: 3px 2px;
border: 1px solid #2a2a3a;
......@@ -395,8 +394,26 @@
cursor: pointer;
}
.portSideSelect {
width: 48px;
.portConnectorInput {
width: 60px;
padding: 3px 5px;
border: 1px solid transparent;
border-radius: 3px;
background: transparent;
color: #6366f1;
font-size: 10px;
font-family: 'Consolas', monospace;
flex-shrink: 0;
}
.portConnectorInput:focus {
outline: none;
border-color: #6366f1;
background: #1a1a28;
}
.portConnectorInput::placeholder {
color: #444;
}
.portDeleteBtn {
......
......@@ -6,12 +6,6 @@ import { PORT_TYPES } from '../../utils/constants';
import useComponentLibrary from '../../hooks/useComponentLibrary';
import styles from './ComponentEditor.module.css';
const SIDES = [
{ value: 'top', label: '上' },
{ value: 'bottom', label: '下' },
{ value: 'left', label: '左' },
{ value: 'right', label: '右' },
];
export default function PortEditor() {
const { editingTemplate, updatePort, removePort, addPort } = useComponentLibrary();
......@@ -76,6 +70,15 @@ export default function PortEditor() {
placeholder="端点描述"
/>
{/* Connector 参数 */}
<input
className={styles.portConnectorInput}
value={port.connector || ''}
onChange={(e) => updatePort(port.id, { connector: e.target.value })}
placeholder="connector"
title="Modelica 端口标识"
/>
{/* 类型选择 */}
<select
className={styles.portTypeSelect}
......@@ -87,17 +90,6 @@ export default function PortEditor() {
))}
</select>
{/* 位置选择 */}
<select
className={styles.portSideSelect}
value={port.side}
onChange={(e) => updatePort(port.id, { side: e.target.value })}
>
{SIDES.map(s => (
<option key={s.value} value={s.value}>{s.label}</option>
))}
</select>
{/* 删除 */}
<button
className={styles.portDeleteBtn}
......
......@@ -97,7 +97,7 @@ export default function PropertiesPanel() {
<div className={styles.portList}>
{(selectedNode.data?.ports || selectedNode.data?.templateData?.ports || []).map(p => (
<span key={typeof p === 'string' ? p : p.id || p} className={styles.portTag}>
{typeof p === 'string' ? p : (p.portId != null ? p.portId : p.name)}
{typeof p === 'string' ? p : (p.connector || p.name)}
</span>
))}
</div>
......
......@@ -68,12 +68,24 @@ export function createBlankTemplate() {
shapes: [],
params: [],
ports: [
{ id: 'in1', portId: 1, name: '1', description: '端点描述', type: 'generic', side: 'left', position: 0.5 },
{ id: 'out1', portId: 2, name: '2', description: '端点描述', type: 'generic', side: 'right', position: 0.5 },
{ id: 'in1', portId: 1, name: '1', description: '', type: 'generic', side: 'left', position: 0.5, connector: 'in1' },
{ id: 'out1', portId: 2, name: '2', description: '', type: 'generic', side: 'right', position: 0.5, connector: 'out1' },
],
};
}
/**
* 根据已有端口列表生成默认 connector 名称和端口编号
* connector 使用 p 前缀:p1, p2, p3...
* 返回 { connector, portNum } 以便同步生成名称 portN
*/
function generateDefaultPortInfo(existingPorts) {
let n = 1;
const usedConnectors = new Set(existingPorts.map(p => p.connector));
while (usedConnectors.has(`p${n}`)) n++;
return { connector: `p${n}`, portNum: n };
}
const useComponentLibrary = create((set, get) => ({
templates: loadFromStorage(),
customCategories: loadCategories(),
......@@ -161,14 +173,18 @@ const useComponentLibrary = create((set, get) => ({
if (!current) return;
get().pushHistory();
const maxPortId = current.ports.reduce((max, p) => Math.max(max, p.portId || 0), 0);
const side = port.side || 'left';
const { connector: defaultConnector, portNum } = generateDefaultPortInfo(current.ports);
const connector = port.connector || defaultConnector;
const newPort = {
id: `port-${Date.now()}`,
portId: maxPortId + 1,
name: `${maxPortId + 1}`,
description: '端点描述',
name: port.name || `port${portNum}`,
description: '',
type: 'generic',
side: 'left',
side,
position: 0.5,
connector,
...port,
};
set({ editingTemplate: { ...current, ports: [...current.ports, newPort] } });
......
......@@ -90,10 +90,11 @@ const useFlowStore = create((set, get) => ({
id: `${p.id}-${counter}`, // 确保端口 id 全局唯一
portId: p.id,
description: '',
connector: p.connector || p.name,
}))
: [
{ id: `p-in-1-${counter}`, name: '输入1', portId: 1, description: '', type: 'generic', side: 'left', position: 0.5 },
{ id: `p-out-1-${counter}`, name: '输出1', portId: 2, description: '', type: 'generic', side: 'right', position: 0.5 },
{ id: `p-in-1-${counter}`, name: '输入1', portId: 1, description: '', type: 'generic', side: 'left', position: 0.5, connector: 'in1' },
{ id: `p-out-1-${counter}`, name: '输出1', portId: 2, description: '', type: 'generic', side: 'right', position: 0.5, connector: 'out1' },
];
const templateData = {
......
This diff is collapsed.
......@@ -152,6 +152,8 @@ export function resolvePortName(handleId, type, ports) {
if (ports && ports.length > 0) {
const port = ports.find(p => p.id === handleId);
if (port) {
// 优先使用 connector 字段
if (port.connector) return port.connector;
const originalId = port.portId || port.id;
// 查映射表
if (mapping && mapping.portMap[originalId]) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment