auto-renaming process changed to abbreviation names with catagoreis, like DC, MMI and PD...

This commit is contained in:
2026-05-29 23:42:10 +08:00
parent 07ee7f9dd7
commit 80d7514740
12 changed files with 162 additions and 292 deletions
+136 -14
View File
@@ -3646,6 +3646,10 @@
if (!activePageId) return;
const relevantChanges = changes.filter(change => change.id !== '__canvas-boundary__');
if (relevantChanges.length === 0) return;
const removedNodeIds = new Set(relevantChanges.filter(change => change.type === 'remove').map(change => change.id));
if (removedNodeIds.size > 0 && activePage) {
releaseComponentDisplayNames(activePage.nodes.filter(node => removedNodeIds.has(node.id)));
}
setPages(prev => prev.map(p => {
if (p.id !== activePageId) return p;
const newNodes = applyNodeChanges(relevantChanges, p.nodes).map(node => {
@@ -3667,7 +3671,7 @@
}
return { ...p, nodes: newNodes, port: newPort };
}));
}, [activePageId, activeCanvasSize]);
}, [activePageId, activePage, activeCanvasSize]);
const onEdgesChange = useCallback((changes) => {
if (!activePageId) return;
@@ -3812,6 +3816,7 @@
const selectedNodes = activePage.nodes.filter(n => n.selected);
if (selectedNodes.length > 0) {
setClipboard({ nodes: JSON.parse(JSON.stringify(selectedNodes)) });
releaseComponentDisplayNames(selectedNodes);
const selectedNodeIds = new Set(selectedNodes.map(n => n.id));
const newNodes = activePage.nodes.filter(n => !selectedNodeIds.has(n.id));
const newEdges = activePage.edges.filter(e => !selectedNodeIds.has(e.source) && !selectedNodeIds.has(e.target));
@@ -3822,7 +3827,13 @@
const handlePaste = useCallback(() => {
if (!activePage || clipboard.nodes.length === 0) return;
const newNodes = clipboard.nodes.map(node => {
const copiedName = generateComponentDisplayName();
const copyCategory = node.data?.libraryCategory && node.data.libraryCategory !== 'basic'
? node.data.libraryCategory
: (node.data?.category && node.data.category !== 'basic' ? node.data.category : '');
const copiedName = generateComponentDisplayName(
copyCategory || node.data?.componentName || node.data?.elementType,
{ singularize: Boolean(copyCategory), abbreviate: Boolean(copyCategory) }
);
const copiedData = {
...node.data,
componentDisplayName: copiedName
@@ -3852,6 +3863,7 @@
const selectedNodes = activePage.nodes.filter(n => n.selected);
const selectedNodeIds = new Set(selectedNodes.map(n => n.id));
if (selectedNodeIds.size > 0) {
releaseComponentDisplayNames(selectedNodes);
const newNodes = activePage.nodes.filter(n => !selectedNodeIds.has(n.id));
const newEdges = activePage.edges.filter(e => !selectedNodeIds.has(e.source) && !selectedNodeIds.has(e.target));
setPages(prev => prev.map(p => p.id === activePage.id ? { ...p, nodes: newNodes, edges: newEdges } : p));
@@ -3899,16 +3911,122 @@
};
}, [handleCopy, handleCut, handlePaste, handleDelete, rotateComponentByNinety, getSpaceRotationTarget, clearSpaceRotateNode]);
const componentCounterRef = useRef(1);
const componentIndexesByPrefixRef = useRef({});
const generateComponentDisplayName = useCallback(() => {
const name = `component_${componentCounterRef.current}`;
componentCounterRef.current += 1;
return name;
const COMPONENT_CATEGORY_PREFIX_ABBREVIATIONS = {
directional_coupler: 'DC',
directional_couplers: 'DC',
multimode_interferometer: 'MMI',
multimode_interferometers: 'MMI',
photodetector: 'PD',
photodetectors: 'PD',
waveguide: 'WG',
waveguides: 'WG',
transition: 'TRX',
transitions: 'TRX',
transistion: 'TRX',
transistions: 'TRX',
Mach_Zender_Modulator: 'MZM',
Mach_Zender_Modulators: 'MZM',
Mach_Zender_modulator: 'MZM',
Mach_Zender_modulators: 'MZM',
mach_zender_modulator: 'MZM',
mach_zender_modulators: 'MZM',
bending: 'BD',
bendings: 'BD',
edge_coupler: 'EC',
edge_couplers: 'EC',
grating_coupler: 'GC',
grating_couplers: 'GC',
termination: 'TERM',
terminations: 'TERM'
};
function parseComponentDisplayName(displayName) {
const match = String(displayName || '').match(/^(.+)_(\d+)$/);
if (!match) return null;
const index = Number(match[2]);
if (!Number.isInteger(index) || index < 1) return null;
return { prefix: match[1], index };
}
function reserveComponentDisplayName(displayName) {
const parsed = parseComponentDisplayName(displayName);
if (!parsed) return;
const usedIndexes = componentIndexesByPrefixRef.current[parsed.prefix] || new Set();
usedIndexes.add(parsed.index);
componentIndexesByPrefixRef.current[parsed.prefix] = usedIndexes;
}
function releaseComponentDisplayName(displayName) {
const parsed = parseComponentDisplayName(displayName);
if (!parsed) return;
const usedIndexes = componentIndexesByPrefixRef.current[parsed.prefix];
if (!usedIndexes) return;
usedIndexes.delete(parsed.index);
if (usedIndexes.size === 0) {
delete componentIndexesByPrefixRef.current[parsed.prefix];
}
}
function releaseComponentDisplayNames(nodes = []) {
nodes.forEach(node => releaseComponentDisplayName(node?.data?.componentDisplayName));
}
function reserveComponentDisplayNamesFromPages() {
pages.forEach(page => {
(page.nodes || []).forEach(node => reserveComponentDisplayName(node?.data?.componentDisplayName));
});
}
const normalizeComponentDisplayNamePrefix = useCallback((prefixSource, options = {}) => {
const cleanedPrefix = String(prefixSource || 'element')
.trim()
.replace(/[\\/]+/g, '_')
.replace(/\s+/g, '_')
.replace(/[^A-Za-z0-9_]+/g, '_')
.replace(/_+/g, '_')
.replace(/^_+|_+$/g, '');
if (!cleanedPrefix) return 'element';
const abbreviation = options.abbreviate
? COMPONENT_CATEGORY_PREFIX_ABBREVIATIONS[cleanedPrefix] || COMPONENT_CATEGORY_PREFIX_ABBREVIATIONS[cleanedPrefix.toLowerCase()]
: '';
if (abbreviation) return abbreviation;
if (!options.singularize) return cleanedPrefix;
const parts = cleanedPrefix.split('_');
const lastIndex = parts.length - 1;
const last = parts[lastIndex];
if (last.length > 3 && last.endsWith('ies')) {
parts[lastIndex] = `${last.slice(0, -3)}y`;
} else if (last.length > 1 && last.endsWith('s')) {
parts[lastIndex] = last.slice(0, -1);
}
const singularPrefix = parts.join('_') || 'element';
if (options.abbreviate) {
return COMPONENT_CATEGORY_PREFIX_ABBREVIATIONS[singularPrefix] || COMPONENT_CATEGORY_PREFIX_ABBREVIATIONS[singularPrefix.toLowerCase()] || singularPrefix;
}
return singularPrefix;
}, []);
const generateComponentDisplayName = useCallback((prefixSource = 'element', options = {}) => {
const prefix = normalizeComponentDisplayNamePrefix(prefixSource, options);
reserveComponentDisplayNamesFromPages();
const usedIndexes = componentIndexesByPrefixRef.current[prefix] || new Set();
let nextIndex = 1;
while (usedIndexes.has(nextIndex)) nextIndex += 1;
const name = `${prefix}_${nextIndex}`;
usedIndexes.add(nextIndex);
componentIndexesByPrefixRef.current[prefix] = usedIndexes;
return name;
}, [normalizeComponentDisplayNamePrefix, pages]);
const renameComponent = useCallback((nodeId, newComponentDisplayName) => {
if (!activePageId) return;
const oldDisplayName = activePage?.nodes.find(node => node.id === nodeId)?.data?.componentDisplayName;
if (oldDisplayName !== newComponentDisplayName) {
releaseComponentDisplayName(oldDisplayName);
reserveComponentDisplayName(newComponentDisplayName);
}
setPages(prev => prev.map(p => {
if (p.id !== activePageId) return p;
return {
@@ -3916,7 +4034,7 @@
nodes: p.nodes.map(n => n.id === nodeId ? { ...n, data: { ...n.data, componentDisplayName: newComponentDisplayName } } : n)
};
}));
}, [activePageId]);
}, [activePageId, activePage]);
const fetchLibrary = useCallback(async () => {
try {
@@ -4788,8 +4906,7 @@
const componentName = parsedData.componentName || parsedData.name;
const basicArguments = createBasicSettings(componentName, parsedData.settings);
const metadata = getBasicComponentMetadata(componentName, basicArguments);
const componentDisplayName = `${componentName.replace(/\s+/g, '_')}_${componentCounterRef.current}`;
componentCounterRef.current += 1;
const componentDisplayName = generateComponentDisplayName(componentName);
const newNode = {
id: Date.now().toString(),
type: 'rotatableNode',
@@ -4815,8 +4932,7 @@
return;
}
if (parsedData.type === 'element') {
const elementName = parsedData.elementType === 'anchor' ? `anchor_${componentCounterRef.current}` : `port_${componentCounterRef.current}`;
componentCounterRef.current += 1;
const elementName = generateComponentDisplayName(parsedData.elementType === 'anchor' ? 'anchor' : 'port');
const isPort = parsedData.elementType === 'port';
const newNode = isPort
? {
@@ -4876,7 +4992,10 @@
return;
}
const selectedIsForge = isForgeComponent(selectedComponent);
const componentDisplayName = generateComponentDisplayName();
const componentDisplayName = generateComponentDisplayName(parsedData.category || selectedComponent, {
singularize: Boolean(parsedData.category),
abbreviate: Boolean(parsedData.category)
});
const newNode = {
id: Date.now().toString(),
type: 'rotatableNode',
@@ -4904,7 +5023,10 @@
});
return;
}
const componentDisplayName = generateComponentDisplayName();
const componentDisplayName = generateComponentDisplayName(parsedData.category || parsedData.name, {
singularize: Boolean(parsedData.category),
abbreviate: Boolean(parsedData.category)
});
const newNode = {
id: Date.now().toString(),
type: 'rotatableNode',