diff --git a/server/__pycache__/main.cpython-310.pyc b/server/__pycache__/main.cpython-310.pyc index 8722869..7f467ca 100644 Binary files a/server/__pycache__/main.cpython-310.pyc and b/server/__pycache__/main.cpython-310.pyc differ diff --git a/server/app/api/__pycache__/endpoints_graph.cpython-310.pyc b/server/app/api/__pycache__/endpoints_graph.cpython-310.pyc index 65482ae..f3e226d 100644 Binary files a/server/app/api/__pycache__/endpoints_graph.cpython-310.pyc and b/server/app/api/__pycache__/endpoints_graph.cpython-310.pyc differ diff --git a/server/app/api/__pycache__/endpoints_upload.cpython-310.pyc b/server/app/api/__pycache__/endpoints_upload.cpython-310.pyc index a017cca..6011105 100644 Binary files a/server/app/api/__pycache__/endpoints_upload.cpython-310.pyc and b/server/app/api/__pycache__/endpoints_upload.cpython-310.pyc differ diff --git a/server/app/api/endpoints_graph.py b/server/app/api/endpoints_graph.py index 9533388..42a183e 100644 --- a/server/app/api/endpoints_graph.py +++ b/server/app/api/endpoints_graph.py @@ -313,7 +313,7 @@ async def ws_execute_graph(websocket: WebSocket): "source_port": s_handle, "target": edge.get("target"), "target_port": t_handle, - "dimension_mode": edge.get("dimension_mode"), + "dimension_mode": DimensionMode(edge.get("dimension_mode")), }) settings = init_msg.get("settings") or {} diff --git a/server/app/api/endpoints_upload.py b/server/app/api/endpoints_upload.py index d76e988..e1440f7 100644 --- a/server/app/api/endpoints_upload.py +++ b/server/app/api/endpoints_upload.py @@ -40,6 +40,8 @@ async def list_files( try: for item in target_path.iterdir(): # 统一使用正斜杠格式 + if item.name.startswith("__"): + continue # 跳过隐藏文件 relative_path = str(item.relative_to(CLOUD_ROOT)).replace('\\', '/') items.append({ "name": item.name, diff --git a/server/app/core/__pycache__/node_base.cpython-310.pyc b/server/app/core/__pycache__/node_base.cpython-310.pyc index c4148cc..5a00d91 100644 Binary files a/server/app/core/__pycache__/node_base.cpython-310.pyc and b/server/app/core/__pycache__/node_base.cpython-310.pyc differ diff --git a/server/app/core/__pycache__/workflow_executor.cpython-310.pyc b/server/app/core/__pycache__/workflow_executor.cpython-310.pyc index 4d292be..64eea5d 100644 Binary files a/server/app/core/__pycache__/workflow_executor.cpython-310.pyc and b/server/app/core/__pycache__/workflow_executor.cpython-310.pyc differ diff --git a/server/app/nodes/__pycache__/trace_loader_nodes.cpython-310.pyc b/server/app/nodes/__pycache__/trace_loader_nodes.cpython-310.pyc index 953cd9f..dfbfc94 100644 Binary files a/server/app/nodes/__pycache__/trace_loader_nodes.cpython-310.pyc and b/server/app/nodes/__pycache__/trace_loader_nodes.cpython-310.pyc differ diff --git a/server/app/nodes/trace_loader_nodes.py b/server/app/nodes/trace_loader_nodes.py index cdee411..a82fea8 100644 --- a/server/app/nodes/trace_loader_nodes.py +++ b/server/app/nodes/trace_loader_nodes.py @@ -65,9 +65,7 @@ class TraceLoader_Metadata(TraceNode): print("TraceLoader_Metadata: process called with utrace_file =", utrace_file, ", tokens =", tokens) if not utrace_file: - time.sleep(3.5) - return {} - #raise ValueError("必须指定 utrace_file 参数") + raise ValueError("必须指定 utrace_file 参数") # 加载系统配置 config = load_system_config() @@ -91,7 +89,7 @@ class TraceLoader_Metadata(TraceNode): # 确保输出目录存在 csv_full_path.parent.mkdir(parents=True, exist_ok=True) - if csv_full_path.exists(): + if csv_full_path.exists() and False: df = pl.read_csv(csv_full_path) return { "metadata": df, diff --git a/server/file_manager.py b/server/file_manager.py index aa8cec9..5f4e232 100644 --- a/server/file_manager.py +++ b/server/file_manager.py @@ -132,6 +132,8 @@ async def list_files( # 获取所有文件和文件夹 items: List[FileInfo] = [] for item in sorted(target_path.iterdir(), key=lambda x: (not x.is_dir(), x.name.lower())): + if item.name.startswith("__"): + continue # 跳过隐藏文件 try: items.append(get_file_info(item)) except Exception as e: diff --git a/server/main.py b/server/main.py index 12d330c..df1301f 100644 --- a/server/main.py +++ b/server/main.py @@ -9,7 +9,7 @@ import yaml from pathlib import Path from server.app.api import endpoints_graph, endpoints_upload -from server.api_spec import mock_schema +from server.tests.api_spec import mock_schema from server.app.core.user_manager import init_base_structure from server.app.core.node_loader import reload_custom_nodes from server.app.core.cache_manager import CacheManager diff --git a/server/api_spec/__pycache__/mock_schema.cpython-310.pyc b/server/tests/api_spec/__pycache__/mock_schema.cpython-310.pyc similarity index 100% rename from server/api_spec/__pycache__/mock_schema.cpython-310.pyc rename to server/tests/api_spec/__pycache__/mock_schema.cpython-310.pyc diff --git a/server/api_spec/__pycache__/mock_schema.cpython-312.pyc b/server/tests/api_spec/__pycache__/mock_schema.cpython-312.pyc similarity index 100% rename from server/api_spec/__pycache__/mock_schema.cpython-312.pyc rename to server/tests/api_spec/__pycache__/mock_schema.cpython-312.pyc diff --git a/server/api_spec/mock_schema.py b/server/tests/api_spec/mock_schema.py similarity index 100% rename from server/api_spec/mock_schema.py rename to server/tests/api_spec/mock_schema.py diff --git a/web/src/core/api/dataAdapter.ts b/web/src/core/api/dataAdapter.ts index cc98f4f..1ad7451 100644 --- a/web/src/core/api/dataAdapter.ts +++ b/web/src/core/api/dataAdapter.ts @@ -6,6 +6,8 @@ /** * 将旧版 nodes/edges 转换为后端执行器期望的格式 */ +import { PortModel } from '../model/PortModel' + export function toExecutorPayload(data: { nodes: any[] edges: any[] @@ -62,14 +64,52 @@ export function toExecutorPayload(data: { } }) - // 转换边 - const edgesOut = edges.map((e: any) => ({ - source: e.source, - source_port: e.source_port || e.sourceHandle?.replace(/^output-/, '') || 'output', - target: e.target, - target_port: e.target_port || e.targetHandle?.replace(/^input-/, '') || 'input', - dimension_mode: e.dimension_mode || 'none' - })) + // Helper: get port type from node meta + const findPortType = (node: any, portName: string, portSide: 'outputs' | 'inputs') => { + const meta = node?.meta || node?.data?.meta || {} + const ports = meta[portSide] || [] + if (!ports || !Array.isArray(ports)) return undefined + const p = ports.find((x: PortModel) => x && x.name === portName) + return PortModel.getTypeInfo(p.type || '') + } + + // 转换边并重新计算 dimension_mode + const edgesOut = edges.map((e: any) => { + const source = e.source + const target = e.target + const source_port = e.source_port + const target_port = e.target_port + + const srcNode = nodes.find((n: any) => n.id === source) || {} + const tgtNode = nodes.find((n: any) => n.id === target) || {} + + const srcInfo = findPortType(srcNode, source_port, 'outputs') + const tgtInfo = findPortType(tgtNode, target_port, 'inputs') + + const upDimension = srcNode.upDimension + const srcDim = (srcInfo.dim || 0) + (upDimension || 0) + const tgtDim = tgtInfo.dim || 0 + + // default to provided or 'none' + let dimension_mode = e.dimension_mode || 'none' + + // If multiple edges into same port, mark as 'up' (collapse/pack) + if (srcDim < tgtDim) { + dimension_mode = 'up' + }else if (srcDim > tgtDim) { + dimension_mode = 'down' + } else { + dimension_mode = 'none' + } + + return { + source, + source_port, + target, + target_port, + dimension_mode + } + }) const payload: any = { nodes: nodesOut, @@ -138,18 +178,3 @@ function normalizeOutputs(raw: any): Array { return [] } -/** - * 获取类型信息 - */ -export function getTypeInfo(type: string = 'any') { - const typeMap: Record = { - 'any': { dim: 1, color: '#8b5cf6' }, - 'number': { dim: 1, color: '#3b82f6' }, - 'string': { dim: 1, color: '#10b981' }, - 'array': { dim: 2, color: '#f59e0b' }, - 'dataframe': { dim: 2, color: '#f59e0b' }, - 'image': { dim: 2, color: '#ec4899' }, - 'tensor': { dim: 3, color: '#ef4444' }, - } - return typeMap[type] || { dim: 1, color: '#6b7280' } -} diff --git a/web/src/core/model/GraphModel.ts b/web/src/core/model/GraphModel.ts index 26c7d9c..13495b9 100644 --- a/web/src/core/model/GraphModel.ts +++ b/web/src/core/model/GraphModel.ts @@ -1,4 +1,5 @@ import NodeModel from './NodeModel' +import { PortModel } from '../model/PortModel' // 类型颜色映射 const TYPE_COLORS: Record = { DataTable: '#3b82f6', // 蓝色 @@ -80,9 +81,9 @@ export class GraphModel { if(!srcNode) continue const srcOutput = srcNode.outputs.find((o:any) => o.name === (e.source_port || 'output')) const tgtInput = node.inputs.find((i:any) => i.name === (e.target_port || 'input')) - const srcDimInfo = srcOutput?.getTypeInfo ? srcOutput.getTypeInfo() : { type: '', dim: 0 } - const tgtDimInfo = tgtInput?.getTypeInfo ? tgtInput.getTypeInfo() : { type: '', dim: 0 } - const srcDim = srcDimInfo.dim || 0 + const srcDimInfo = PortModel.getTypeInfo(srcOutput?.type || '') + const tgtDimInfo = PortModel.getTypeInfo(tgtInput?.type || '') + const srcDim = srcDimInfo.dim || 0 + (srcNode.upDimension || 0) const tgtDim = tgtDimInfo.dim || 0 const diff = srcDim - tgtDim if(diff > newUp) newUp = diff diff --git a/web/src/core/model/PortModel.ts b/web/src/core/model/PortModel.ts index c499981..75045e9 100644 --- a/web/src/core/model/PortModel.ts +++ b/web/src/core/model/PortModel.ts @@ -8,7 +8,10 @@ export class PortModel { } getTypeInfo(): {type: string; dim: number } { - const type = this.type + const result = PortModel.getTypeInfo(this.type || '') + return result + } + static getTypeInfo(type: string): {type: string; dim: number } { if (!type) return {type: '', dim: 0 } const str = String(type).trim() if (typeDimMap.has(str)) return typeDimMap.get(str)! diff --git a/web/src/core/model/StudioRuntime.ts b/web/src/core/model/StudioRuntime.ts index 8748ccb..aaf2995 100644 --- a/web/src/core/model/StudioRuntime.ts +++ b/web/src/core/model/StudioRuntime.ts @@ -119,7 +119,7 @@ export class StudioRuntime { } public exportWorkflow(){ if(!this.graph) return { nodes: [], edges: [] } - const nodes = Array.from(this.graph.nodes.values()).map(n => ({ id: n.id, schemaName: n.schemaName, position: n.position, params: n.params, meta: n.meta })) + const nodes = Array.from(this.graph.nodes.values()).map(n => ({ id: n.id, schemaName: n.schemaName, position: n.position, params: n.params, meta: n.meta , upDimension: n.upDimension } )) const edges = Array.from(this.graph.edges.values()).map((e:any) => ({ id: e.id, source: e.source, source_port: e.source_port, target: e.target, target_port: e.target_port, dimension_mode: e.dimension_mode, style: e.style, animated: !!e.animated })) const viewport = this.viewport || null return { nodes, edges, viewport } diff --git a/web/src/core/services/GraphService.ts b/web/src/core/services/GraphService.ts index b441563..f82ea45 100644 --- a/web/src/core/services/GraphService.ts +++ b/web/src/core/services/GraphService.ts @@ -1,5 +1,6 @@ import useRuntimeStore from '../store/runtimeStore' import { runtime } from '../model/StudioRuntime' +import { PortModel } from '../model/PortModel'; const GraphService = { // Graph mutations @@ -16,8 +17,8 @@ const GraphService = { const srcOutput = srcModel.outputs.find((o: any) => o.name === srcPort) const tgtInput = tgtModel.inputs.find((i: any) => i.name === tgtPort) - const srcTypeInfo = srcOutput?.getTypeInfo() || { type: '', dim: 0 } - const tgtTypeInfo = tgtInput?.getTypeInfo() || { type: '', dim: 0 } + const srcTypeInfo = PortModel.getTypeInfo(srcOutput?.type || '') + const tgtTypeInfo = PortModel.getTypeInfo(tgtInput?.type || '') if(srcTypeInfo.type != tgtTypeInfo.type){ console.warn('GraphService.createEdge: type mismatch'); return null } const srcDim = srcTypeInfo.dim + srcModel.upDimension