import { getStepLine, Step, traversalSteps } from "./tree-helper"; import { getStepsTreeCtx as getStepsTreeCtxRaw, StepsCtx as StepsCtxRaw, } from "./tree-helper"; type DataStep = { serviceTypeParallel?: boolean | "True" | "Flase"; subStepsParallel?: boolean | "True" | "Flase"; }; export type DataStepTree = T & { steps: DataStepTree[]; }; export type NStep = Step; const _flatSteps = ( steps: DataStepTree[], nsteps: NStep>[] = [], parents: NStep>[] = [], parallel = false ) => { const lonelySteps: NStep>[] = []; let tempParents = parents; for (const step of steps) { const stepParallel = parallel; if (!stepParallel && lonelySteps.length) { tempParents = [...lonelySteps]; lonelySteps.length = 0; } const nstep = { raw: step, children: [], parents: tempParents, } as NStep>; nsteps.push(nstep); tempParents.forEach((parent) => parent.children.push(nstep)); if (step.steps && step.steps.length) { step.serviceTypeParallel; lonelySteps.push( ..._flatSteps( step.steps, nsteps, [nstep], step.subStepsParallel === "True" || step.serviceTypeParallel === "True" || !!step.subStepsParallel || !!step.serviceTypeParallel ) ); } else { lonelySteps.push(nstep); } } return lonelySteps; }; export const flatSteps = (steps: DataStepTree[]) => { const nsteps: NStep>[] = []; _flatSteps(steps, nsteps); return nsteps; }; // 获取step所有子级 const getStepFlatSteps = (step: DataStepTree) => { if (!step.steps || step.steps.length === 0) return []; const children: DataStepTree[] = []; for (const child of step.steps) { children.push(child); children.push(...getStepFlatSteps(child)); } return children; }; // 获取steps组成的bound const getStepsBound = (nsteps: NStep>[]) => { const bounds = nsteps.map((nstep) => { return { ...nstep.box.offset, ...nstep.box.size }; }); let maxX = -Number.MAX_VALUE, maxY = -Number.MAX_VALUE, minX = Number.MAX_VALUE, minY = Number.MAX_VALUE; for (const bound of bounds) { minX = Math.min(bound.x, minX); minY = Math.min(bound.y, minY); maxX = Math.max(bound.x + bound.w, maxX); maxY = Math.max(bound.y + bound.h, maxY); } return { x: minX, y: minY, w: maxX - minX, h: maxY - minY, }; }; export type StepsCtx = StepsCtxRaw & { groupBoxs: { step: Step; bound: { w: number; h: number; x: number; y: number }; line: number[][]; }[]; }; const setGroupBack = ( steps: NStep>[], ctx: StepsCtx>, groups: NStep>[] ) => { const maxWidth = Math.max(...groups.map(({ box }) => box.size.w)); for (const groupStep of groups) { const children = getStepFlatSteps(groupStep.raw); const childSteps = children.map((raw) => steps.find((step) => raw === step.raw) ); ctx.groupBoxs.push({ step: groupStep, line: [], bound: getStepsBound(childSteps), }); groupStep.box.offset.x = -maxWidth + (maxWidth - groupStep.box.size.w) / 2; } ctx.offset.x = -maxWidth; ctx.size.w += maxWidth; }; const setGroupOffset = ( steps: NStep>[], ctx: StepsCtx>, groupSteps: NStep>[], margin: number ) => { // margin = 0; const offsetYs: number[] = []; const offsetLYs: number[] = []; for (let i = 0; i < groupSteps.length; i++) { const groupStep = groupSteps[i]; if (i > 0) { offsetYs[i] = -groupStep.box.size.h + offsetYs[i - 1] + margin; offsetLYs[i] = offsetLYs[i - 1] - groupStep.box.size.h + margin; } else { offsetYs[i] = -groupStep.box.size.h + margin; offsetLYs[i] = -groupStep.box.size.h + margin; } groupStep.box.offset.y += margin; } let offsetNdx = offsetYs.length - 1; let offsetLNdx = offsetYs.length - 1; traversalSteps({ steps, ctx, oper: ({ currents }) => { const isBorder = currents.some((current) => groupSteps.includes(current)); if (isBorder) { offsetNdx -= 1; } for (const current of currents) { if (offsetNdx === -1) { current.box.lines = []; break; } current.box.offset.y += offsetYs[offsetNdx]; for (const points of current.box.lines) { for (const point of points) { point[1] = point[1] + offsetLYs[offsetLNdx]; } } } if (isBorder) { offsetLNdx -= 1; } }, reverse: true, }); ctx.size.h += offsetYs[offsetYs.length - 1]; }; export const setGroupLine = ( ctx: StepsCtx>, groupSteps: NStep>[], margin: number[] ) => { for (let i = 0; i < groupSteps.length - 1; i++) { ctx.groupBoxs[i].line = getStepLine( ctx, groupSteps[i], groupSteps[i + 1], margin ); } }; export const getStepsTreeCtx = ( steps: NStep>[], margin: number[], getStepSize: (step: T) => { w: number; h: number }, groups: DataStepTree[] ) => { const ctx = getStepsTreeCtxRaw(steps, margin, getStepSize) as StepsCtx< DataStepTree >; const groupSteps = groups.map((group) => steps.find((step) => group === step.raw) ); setGroupOffset(steps, ctx, groupSteps, margin[0]); ctx.groupBoxs = []; setGroupBack(steps, ctx, groupSteps); setGroupLine(ctx, groupSteps, margin); return ctx; };