181 lines
5.1 KiB
TypeScript
181 lines
5.1 KiB
TypeScript
/**
|
|
* 旧版数据格式适配层
|
|
* 将旧版前端数据格式转换为后端期望的协议格式
|
|
*/
|
|
|
|
/**
|
|
* 将旧版 nodes/edges 转换为后端执行器期望的格式
|
|
*/
|
|
import { PortModel } from '../model/PortModel'
|
|
|
|
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
|
|
}
|
|
})
|
|
|
|
// 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,
|
|
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 []
|
|
}
|
|
|