helper-v2.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import { getStepLine, Step, Steps } from "./tree-helper";
  2. import {
  3. getStepsTreeCtx as getStepsTreeCtxRaw,
  4. StepsCtx as StepsCtxRaw,
  5. } from "./tree-helper";
  6. type DataStep = {
  7. serviceTypeParallel?: boolean | "True" | "Flase";
  8. subStepsParallel?: boolean | "True" | "Flase";
  9. structure?: string;
  10. };
  11. export type DataStepTree<T extends DataStep = DataStep> = T & {
  12. steps: DataStepTree<T>[];
  13. };
  14. export type NStep<T extends DataStepTree> = Step<T>;
  15. const _flatSteps = <T extends DataStep>(
  16. steps: DataStepTree<T>[],
  17. nsteps: NStep<DataStepTree<T>>[] = [],
  18. parents: NStep<DataStepTree<T>>[] = [],
  19. parallel = false
  20. ) => {
  21. const lonelySteps: NStep<DataStepTree<T>>[] = [];
  22. let tempParents = parents;
  23. for (const step of steps) {
  24. const stepParallel = parallel;
  25. if (!stepParallel && lonelySteps.length) {
  26. tempParents = [...lonelySteps];
  27. lonelySteps.length = 0;
  28. }
  29. const nstep = {
  30. raw: step,
  31. children: [],
  32. parents: tempParents,
  33. } as NStep<DataStepTree<T>>;
  34. nsteps.push(nstep);
  35. tempParents.forEach((parent) => parent.children.push(nstep));
  36. if (step.steps && step.steps.length) {
  37. step.serviceTypeParallel;
  38. lonelySteps.push(
  39. ..._flatSteps(
  40. step.steps,
  41. nsteps,
  42. [nstep],
  43. step.subStepsParallel === "True" ||
  44. step.serviceTypeParallel === "True" ||
  45. !!step.subStepsParallel ||
  46. !!step.serviceTypeParallel
  47. )
  48. );
  49. } else {
  50. lonelySteps.push(nstep);
  51. }
  52. }
  53. return lonelySteps;
  54. };
  55. const start: any = { displayName: "开始", type: "startEnd" };
  56. const end: any = { displayName: "结束", type: "startEnd" };
  57. export const flatSteps = <T extends DataStep>(steps: DataStepTree<T>[]) => {
  58. const nsteps: NStep<DataStepTree<T>>[] = [];
  59. for (let i = 0; i < steps.length; i++) {
  60. // steps[i].steps = [
  61. // {
  62. // ...steps[i],
  63. // subStepsParallel: false,
  64. // structure: "right",
  65. // },
  66. // ];
  67. steps[i].structure = "left";
  68. }
  69. _flatSteps([start, ...steps, end] as any, nsteps);
  70. return {
  71. steps: nsteps,
  72. group: steps,
  73. };
  74. };
  75. // 获取step所有子级
  76. const getStepFlatSteps = <T extends DataStep>(step: DataStepTree<T>) => {
  77. if (!step.steps || step.steps.length === 0) return [];
  78. const children: DataStepTree<T>[] = [];
  79. for (const child of step.steps) {
  80. children.push(child);
  81. children.push(...getStepFlatSteps(child));
  82. }
  83. return children;
  84. };
  85. // 获取steps组成的bound
  86. const getStepsBound = <T>(nsteps: NStep<DataStepTree<T>>[]) => {
  87. const bounds = nsteps.map((nstep) => {
  88. return { ...nstep.box.offset, ...nstep.box.size };
  89. });
  90. let maxX = -Number.MAX_VALUE,
  91. maxY = -Number.MAX_VALUE,
  92. minX = Number.MAX_VALUE,
  93. minY = Number.MAX_VALUE;
  94. for (const bound of bounds) {
  95. minX = Math.min(bound.x, minX);
  96. minY = Math.min(bound.y, minY);
  97. maxX = Math.max(bound.x + bound.w, maxX);
  98. maxY = Math.max(bound.y + bound.h, maxY);
  99. }
  100. return {
  101. x: minX,
  102. y: minY,
  103. w: maxX - minX,
  104. h: maxY - minY,
  105. };
  106. };
  107. export type StepsCtx<T> = StepsCtxRaw<T> & {
  108. groupBoxs: {
  109. step: Step<T>;
  110. bound: { w: number; h: number; x: number; y: number };
  111. line: number[][];
  112. }[];
  113. };
  114. const setGroupBack = <T>(
  115. steps: NStep<DataStepTree<T>>[],
  116. ctx: StepsCtx<DataStepTree<T>>,
  117. groups: NStep<DataStepTree<T>>[]
  118. ) => {
  119. const maxWidth = Math.max(...groups.map(({ box }) => box.size.w));
  120. for (const groupStep of groups) {
  121. const children = getStepFlatSteps(groupStep.raw);
  122. const childSteps = children.map((raw) =>
  123. steps.find((step) => raw === step.raw)
  124. );
  125. ctx.groupBoxs.push({
  126. step: groupStep,
  127. line: [],
  128. bound: getStepsBound(childSteps),
  129. });
  130. groupStep.box.offset.x = -maxWidth + (maxWidth - groupStep.box.size.w) / 2;
  131. }
  132. ctx.offset.x = -maxWidth;
  133. ctx.size.w += maxWidth;
  134. };
  135. const levelTraversalSteps = <T>(
  136. steps: Steps<T>,
  137. oper: (steps: Step<T>[]) => void,
  138. reverse = false,
  139. level = 0
  140. ) => {
  141. const cSteps = steps.filter((item) => item.box.level === level);
  142. if (cSteps.length === 0) return;
  143. reverse || oper(cSteps);
  144. levelTraversalSteps(steps, oper, reverse, level + 1);
  145. reverse && oper(cSteps);
  146. };
  147. const setGroupOffset = <T>(
  148. steps: NStep<DataStepTree<T>>[],
  149. ctx: StepsCtx<DataStepTree<T>>,
  150. groupSteps: NStep<DataStepTree<T>>[],
  151. margin: number
  152. ) => {
  153. // margin = 0;
  154. const offsetYs: number[] = [];
  155. const offsetLYs: number[] = [];
  156. for (let i = 0; i < groupSteps.length; i++) {
  157. const groupStep = groupSteps[i];
  158. if (start === groupStep.raw) {
  159. offsetYs[i] = 0;
  160. offsetLYs[i] = 0;
  161. // offsetLYs[i] = -groupStep.box.size.h + margin;
  162. } else if (end === groupStep.raw) {
  163. offsetYs[i] = offsetYs[i - 1];
  164. offsetLYs[i] = offsetLYs[i - 1];
  165. } else if (i > 0) {
  166. offsetYs[i] = -groupStep.box.size.h + offsetYs[i - 1] + margin;
  167. offsetLYs[i] = offsetLYs[i - 1] - groupStep.box.size.h + margin;
  168. } else {
  169. offsetYs[i] = -groupStep.box.size.h + margin;
  170. offsetLYs[i] = -groupStep.box.size.h + margin;
  171. }
  172. groupStep.box.offset.y += margin;
  173. }
  174. let offsetNdx = offsetYs.length - 1;
  175. let offsetLNdx = offsetYs.length - 1;
  176. let prevG = null;
  177. levelTraversalSteps(
  178. steps,
  179. (currents) => {
  180. const isBorder = currents.some((current) => groupSteps.includes(current));
  181. if (isBorder) {
  182. offsetNdx -= 1;
  183. }
  184. for (const current of currents) {
  185. if (end === prevG || offsetNdx <= 0) {
  186. current.box.lines = [];
  187. }
  188. if (offsetNdx === -1) {
  189. break;
  190. }
  191. current.box.offset.y += offsetYs[offsetNdx];
  192. for (const points of current.box.lines) {
  193. for (const point of points) {
  194. point[1] = point[1] + offsetLYs[offsetLNdx];
  195. }
  196. }
  197. }
  198. prevG = currents[0].raw;
  199. if (isBorder) {
  200. offsetLNdx -= 1;
  201. }
  202. },
  203. true
  204. );
  205. ctx.size.h += offsetYs[offsetYs.length - 1];
  206. };
  207. export const setGroupLine = <T>(
  208. ctx: StepsCtx<DataStepTree<T>>,
  209. groupSteps: NStep<DataStepTree<T>>[],
  210. margin: number[]
  211. ) => {
  212. for (let i = 0; i < groupSteps.length - 1; i++) {
  213. ctx.groupBoxs[i].line = getStepLine(
  214. ctx,
  215. groupSteps[i],
  216. groupSteps[i + 1],
  217. margin
  218. );
  219. }
  220. };
  221. export const getStepsTreeCtx = <T extends DataStep>(
  222. steps: NStep<DataStepTree<T>>[],
  223. margin: number[],
  224. getStepSize: (step: T) => { w: number; h: number },
  225. groups: DataStepTree<T>[]
  226. ) => {
  227. const ctx = getStepsTreeCtxRaw(steps, margin, getStepSize) as StepsCtx<
  228. DataStepTree<T>
  229. >;
  230. console.log(steps, groups);
  231. groups = [start, ...groups, end];
  232. const groupSteps = groups.map((group) =>
  233. steps.find((step) => group === step.raw)
  234. );
  235. ctx.groupBoxs = [];
  236. setGroupOffset(steps, ctx, groupSteps, margin[0]);
  237. setGroupBack(steps, ctx, groupSteps);
  238. setGroupLine(ctx, groupSteps, margin);
  239. return ctx;
  240. };