TraceStudio-dev/web/src/core/api/dataAdapter.ts

181 lines
5.1 KiB
TypeScript
Raw Normal View History

2026-01-12 03:32:51 +08:00
/**
*
*
*/
/**
* nodes/edges
*/
2026-01-12 11:13:01 +08:00
import { PortModel } from '../model/PortModel'
2026-01-12 03:32:51 +08:00
export function toExecutorPayload(data: {
nodes: any[]
edges: any[]
settings?: any
globalContext?: any
}) {
const { nodes, edges, settings, globalContext } = data
// 转换节点
const buildParams = (node: any) => {
if (node.params && typeof node.params === 'object') return node.params
const meta = node.meta || node.data?.meta || {}
const schema = meta.param_schema
if (schema) {
let names: string[] = []
if (Array.isArray(schema)) {
names = schema.map((s: any) => s && s.name).filter(Boolean)
} else if (schema && typeof schema === 'object') {
names = Object.keys(schema)
}
const out: Record<string, any> = {}
names.forEach((k) => {
if (node.data && Object.prototype.hasOwnProperty.call(node.data, k)) out[k] = node.data[k]
else if (node.params && Object.prototype.hasOwnProperty.call(node.params, k)) out[k] = node.params[k]
else out[k] = null
})
return out
}
const source = (node.params && typeof node.params === 'object') ? node.params : (node.data && typeof node.data === 'object' ? node.data : {})
const reserved = new Set(['meta', 'label', 'position', 'updim', 'file_path', 'file', 'dirty'])
const out: Record<string, any> = {}
Object.entries(source).forEach(([k, v]) => {
if (!reserved.has(k)) out[k] = v
})
return out
}
const nodesOut = nodes.map((n: any) => {
// Support both React-view nodes and exported workflow nodes
const className = n.class_name || n.data?.meta?.class_name || n.schemaName || (n.meta && n.meta.class_name) || n.type || 'UnknownNode'
const nodeTypeRaw = n.data?.meta?.node_type || n.meta?.node_type || n.node_type || 'normal'
const nodeType = nodeTypeRaw ? nodeTypeRaw.toString().toLowerCase() : 'normal'
return {
id: n.id,
node_type: nodeType,
class_name: className,
params: buildParams(n),
sub_workflow_nodes: n.sub_workflow_nodes || n.sub_workflow?.nodes || null,
sub_workflow_edges: n.sub_workflow_edges || n.sub_workflow?.edges || null
}
})
2026-01-12 11:13:01 +08:00
// 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
}
})
2026-01-12 03:32:51 +08:00
const payload: any = {
nodes: nodesOut,
edges: edgesOut
}
if (settings) payload.settings = settings
if (globalContext) payload.global_context = globalContext
return payload
}
/**
* meta
*/
export function transformNodeMeta(meta: any) {
return {
...meta,
display_name: meta.display_name || meta.name || 'Unknown',
category: meta.category || 'Other',
param_schema: normalizeParamSchema(meta.param_schema),
inputs: normalizeInputs(meta.inputs),
outputs: normalizeOutputs(meta.outputs)
}
}
/**
*
*/
function normalizeParamSchema(raw: any): Array<any> {
if (Array.isArray(raw)) return raw
if (raw && typeof raw === 'object') {
return Object.entries(raw).map(([name, spec]: [string, any]) => ({
name,
...(spec || {})
}))
}
return []
}
/**
*
*/
function normalizeInputs(raw: any): Array<any> {
if (Array.isArray(raw)) return raw
if (raw && typeof raw === 'object') {
return Object.entries(raw).map(([name, spec]: [string, any]) => ({
name,
...(spec || {})
}))
}
return []
}
/**
*
*/
function normalizeOutputs(raw: any): Array<any> {
if (Array.isArray(raw)) return raw
if (raw && typeof raw === 'object') {
return Object.entries(raw).map(([name, spec]: [string, any]) => ({
name,
...(spec || {})
}))
}
return []
}