代码修改
This commit is contained in:
1 parent
8f5af46ec2
commit
8f75e12871
168 files changed
+76575
No files matched your search
@@ -0,0 +1,266 @@
|
||||
import type {
|
||||
ActorCard,
|
||||
BehaviorDriverCard,
|
||||
NarrativeCard,
|
||||
PurposeCard,
|
||||
SubStepKey,
|
||||
} from './types';
|
||||
|
||||
export interface LayoutNode {
|
||||
id: string;
|
||||
level: number;
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
variant: 'agent' | 'purpose' | 'actor' | 'behavior' | 'driver' | 'narrative';
|
||||
title: string;
|
||||
detail: string;
|
||||
children: string[];
|
||||
parent?: string;
|
||||
}
|
||||
|
||||
export interface LayoutEdge {
|
||||
id: string;
|
||||
fromId: string;
|
||||
toId: string;
|
||||
pair: 'agent-purpose' | 'purpose-actor' | 'actor-behavior' | 'behavior-driver' | 'driver-narrative';
|
||||
}
|
||||
|
||||
export interface FlowLayout {
|
||||
nodes: LayoutNode[];
|
||||
edges: LayoutEdge[];
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface BuildLayoutOptions {
|
||||
nodeWidth?: number;
|
||||
nodeHeight?: number;
|
||||
levelGap?: number;
|
||||
nodeGap?: number;
|
||||
paddingX?: number;
|
||||
paddingY?: number;
|
||||
rootTitle?: string;
|
||||
rootDetail?: string;
|
||||
}
|
||||
|
||||
export const CURRENT_PAIR_BY_STAGE: Record<SubStepKey, LayoutEdge['pair'] | null> = {
|
||||
purpose: 'agent-purpose',
|
||||
actor: 'purpose-actor',
|
||||
behavior: 'actor-behavior',
|
||||
narrative: 'driver-narrative',
|
||||
};
|
||||
|
||||
export const STATUS_TITLE: Record<SubStepKey, string> = {
|
||||
purpose: '正在生成目的中',
|
||||
actor: '正在生成行为体中',
|
||||
behavior: '正在生成预期行为和驱动因素中',
|
||||
narrative: '正在生成叙事中',
|
||||
};
|
||||
|
||||
export const EDGE_COLOR: Record<LayoutEdge['pair'], { dark: string; light: string }> = {
|
||||
'agent-purpose': { dark: '#a78bfa', light: '#fb923c' },
|
||||
'purpose-actor': { dark: '#22d3ee', light: '#ef4444' },
|
||||
'actor-behavior': { dark: '#34d399', light: '#10b981' },
|
||||
'behavior-driver': { dark: '#5eead4', light: '#0d9488' },
|
||||
'driver-narrative': { dark: '#fbbf24', light: '#f59e0b' },
|
||||
};
|
||||
|
||||
export const EDGE_LABEL: Record<LayoutEdge['pair'], string> = {
|
||||
'agent-purpose': '智能体→目的',
|
||||
'purpose-actor': '目的→行为体',
|
||||
'actor-behavior': '行为体→预期行为',
|
||||
'behavior-driver': '预期行为→驱动因素',
|
||||
'driver-narrative': '驱动因素→叙事',
|
||||
};
|
||||
|
||||
export function buildEdgePath(from: LayoutNode, to: LayoutNode): string {
|
||||
const x1 = from.x + from.width / 2;
|
||||
const y1 = from.y + from.height;
|
||||
const x2 = to.x + to.width / 2;
|
||||
const y2 = to.y;
|
||||
const my = (y1 + y2) / 2;
|
||||
return `M ${x1} ${y1} C ${x1} ${my}, ${x2} ${my}, ${x2} ${y2}`;
|
||||
}
|
||||
|
||||
export function buildLayout(
|
||||
purposes: PurposeCard[],
|
||||
actors: ActorCard[],
|
||||
behaviors: BehaviorDriverCard[],
|
||||
narratives: NarrativeCard[],
|
||||
options: BuildLayoutOptions = {},
|
||||
): FlowLayout {
|
||||
const NODE_WIDTH = options.nodeWidth ?? 200;
|
||||
const NODE_HEIGHT = options.nodeHeight ?? 84;
|
||||
const LEVEL_GAP = options.levelGap ?? 130;
|
||||
const NODE_GAP = options.nodeGap ?? 28;
|
||||
const PADDING_X = options.paddingX ?? 48;
|
||||
const PADDING_Y = options.paddingY ?? 40;
|
||||
const rootTitle = options.rootTitle?.trim() || '智能体';
|
||||
const rootDetail = options.rootDetail?.trim() || '协同推演 6 步法生成内容';
|
||||
|
||||
const nodes: LayoutNode[] = [];
|
||||
const nodeMap = new Map<string, LayoutNode>();
|
||||
const push = (node: LayoutNode) => {
|
||||
nodes.push(node);
|
||||
nodeMap.set(node.id, node);
|
||||
};
|
||||
|
||||
const agent: LayoutNode = {
|
||||
id: 'agent-root',
|
||||
level: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: NODE_WIDTH,
|
||||
height: NODE_HEIGHT,
|
||||
variant: 'agent',
|
||||
title: rootTitle,
|
||||
detail: rootDetail,
|
||||
children: purposes.map((p) => p.id),
|
||||
};
|
||||
push(agent);
|
||||
|
||||
purposes.forEach((p) => {
|
||||
push({
|
||||
id: p.id,
|
||||
level: 1,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: NODE_WIDTH,
|
||||
height: NODE_HEIGHT,
|
||||
variant: 'purpose',
|
||||
title: p.title,
|
||||
detail: p.reason,
|
||||
children: actors.filter((a) => a.purposeId === p.id).map((a) => a.id),
|
||||
parent: 'agent-root',
|
||||
});
|
||||
});
|
||||
|
||||
actors.forEach((a) => {
|
||||
push({
|
||||
id: a.id,
|
||||
level: 2,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: NODE_WIDTH,
|
||||
height: NODE_HEIGHT,
|
||||
variant: 'actor',
|
||||
title: a.title,
|
||||
detail: a.content,
|
||||
children: behaviors.filter((b) => b.actorId === a.id).map((b) => `${b.id}-behavior`),
|
||||
parent: a.purposeId,
|
||||
});
|
||||
});
|
||||
|
||||
behaviors.forEach((b) => {
|
||||
const behaviorId = `${b.id}-behavior`;
|
||||
const driverId = `${b.id}-driver`;
|
||||
push({
|
||||
id: behaviorId,
|
||||
level: 3,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: NODE_WIDTH,
|
||||
height: NODE_HEIGHT,
|
||||
variant: 'behavior',
|
||||
title: '预期行为',
|
||||
detail: b.expectedBehavior,
|
||||
children: [driverId],
|
||||
parent: b.actorId,
|
||||
});
|
||||
push({
|
||||
id: driverId,
|
||||
level: 4,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: NODE_WIDTH,
|
||||
height: NODE_HEIGHT,
|
||||
variant: 'driver',
|
||||
title: '驱动因素',
|
||||
detail: b.driver,
|
||||
children: narratives.filter((n) => n.driverId === b.id).map((n) => n.id),
|
||||
parent: behaviorId,
|
||||
});
|
||||
});
|
||||
|
||||
narratives.forEach((n) => {
|
||||
push({
|
||||
id: n.id,
|
||||
level: 5,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: NODE_WIDTH,
|
||||
height: NODE_HEIGHT,
|
||||
variant: 'narrative',
|
||||
title: n.title,
|
||||
detail: n.reason,
|
||||
children: [],
|
||||
parent: `${n.driverId}-driver`,
|
||||
});
|
||||
});
|
||||
|
||||
const leafCounter = { v: 0 };
|
||||
const place = (node: LayoutNode) => {
|
||||
if (node.children.length === 0) {
|
||||
node.x = PADDING_X + leafCounter.v * (NODE_WIDTH + NODE_GAP);
|
||||
leafCounter.v += 1;
|
||||
return;
|
||||
}
|
||||
node.children.forEach((cid) => {
|
||||
const child = nodeMap.get(cid);
|
||||
if (child) place(child);
|
||||
});
|
||||
const xs = node.children.map((cid) => nodeMap.get(cid)?.x ?? 0).filter((v) => v >= 0);
|
||||
if (xs.length > 0) {
|
||||
node.x = (Math.min(...xs) + Math.max(...xs)) / 2;
|
||||
} else {
|
||||
node.x = PADDING_X;
|
||||
}
|
||||
};
|
||||
place(agent);
|
||||
|
||||
nodes.forEach((node) => {
|
||||
node.y = PADDING_Y + node.level * (NODE_HEIGHT + LEVEL_GAP);
|
||||
});
|
||||
|
||||
const edges: LayoutEdge[] = [];
|
||||
nodes.forEach((node) => {
|
||||
node.children.forEach((cid) => {
|
||||
const child = nodeMap.get(cid);
|
||||
if (!child) return;
|
||||
let pair: LayoutEdge['pair'];
|
||||
if (node.variant === 'agent') pair = 'agent-purpose';
|
||||
else if (node.variant === 'purpose') pair = 'purpose-actor';
|
||||
else if (node.variant === 'actor') pair = 'actor-behavior';
|
||||
else if (node.variant === 'behavior') pair = 'behavior-driver';
|
||||
else pair = 'driver-narrative';
|
||||
edges.push({ id: `${node.id}->${cid}`, fromId: node.id, toId: cid, pair });
|
||||
});
|
||||
});
|
||||
|
||||
const allLevels = Math.max(...nodes.map((n) => n.level));
|
||||
const maxX = Math.max(...nodes.map((n) => n.x + n.width));
|
||||
const totalWidth = maxX + PADDING_X;
|
||||
const totalHeight = PADDING_Y * 2 + (allLevels + 1) * NODE_HEIGHT + allLevels * LEVEL_GAP;
|
||||
|
||||
return { nodes, edges, width: totalWidth, height: totalHeight };
|
||||
}
|
||||
|
||||
export const VARIANT_ABBREV: Record<LayoutNode['variant'], string> = {
|
||||
agent: 'AI',
|
||||
purpose: 'md',
|
||||
actor: 'xwt',
|
||||
behavior: 'yqxw',
|
||||
driver: 'qdys',
|
||||
narrative: 'xs',
|
||||
};
|
||||
|
||||
export const VARIANT_LABEL: Record<LayoutNode['variant'], string> = {
|
||||
agent: '智能体',
|
||||
purpose: '目的',
|
||||
actor: '行为体',
|
||||
behavior: '预期行为',
|
||||
driver: '驱动因素',
|
||||
narrative: '叙事',
|
||||
};
|
||||
Reference in new issue
Block a user