浏览代码

feat: 架构搭建

bill 1 年之前
父节点
当前提交
f79c103fcc

+ 2 - 0
src/board/index.ts

@@ -0,0 +1,2 @@
+export * from "./packages";
+export * from "./register";

+ 78 - 73
src/board/packages/container.ts

@@ -1,105 +1,110 @@
-import { reactive, watch } from "vue";
-import { Attrib, EntityClass } from "../type";
+import { watch } from "vue";
+import { Attrib, ShapeType } from "../type";
 import { Layer } from "konva/lib/Layer";
-import { PackageBase } from "../shared/package-base";
+import { Entity, EntityProps, EntityType } from "./entity";
 import { Stage } from "konva/lib/Stage";
 import {
-  attribsJoinEntity,
-  depPartialUpdate,
-  getChangePart,
-} from "../shared/util";
-import { mergeFuns } from "../../util";
+  IncEntitysFactory,
+  incEntitysFactoryGenerate,
+} from "../shared/entity-utils";
 
-export type ContainerProps<T extends string, R extends Attrib> = {
+export type ContainerProps<
+  T extends string,
+  R extends Attrib,
+  S extends ShapeType,
+  C extends EntityType<R, S>
+> = {
   types: {
-    [key in T]: EntityClass<R>;
+    [key in T]: C;
   };
   data?: { [key in T]?: R[] };
   dom: HTMLDivElement;
-};
+} & Omit<EntityProps<Attrib & { data: { [key in T]?: R[] } }>, "attrib">;
 
-export class Container<T extends string, R extends Attrib> extends PackageBase<
-  Attrib,
-  Stage
-> {
-  props: ContainerProps<T, R>;
-  data: { [key in T]?: R[] };
-  entrys = {} as { [key in T]: InstanceType<EntityClass<R>>[] };
-  viewLayer: Layer;
+export class Container<
+  T extends string,
+  R extends Attrib,
+  S extends ShapeType,
+  C extends EntityType<R, S>
+> extends Entity<Attrib & { data: { [key in T]?: R[] } }, Layer> {
+  config: ContainerProps<T, R, S, C>;
+  entrys = {} as { [key in T]: InstanceType<C>[] };
   tempLayer: Layer;
+  stage: Stage;
+  incFactorys = {} as {
+    [key in T]: IncEntitysFactory<R, InstanceType<C>>;
+  };
 
-  constructor(props: ContainerProps<T, R>) {
-    super({ name: "container", attrib: { id: "0" } });
-    this.props = props;
-    this.data = reactive(props.data || {});
-    for (const key in props.types) {
-      this.data[key] = this.data[key] || [];
+  constructor(config: ContainerProps<T, R, S, C>) {
+    for (const key in config.types) {
+      config.data[key] = config.data[key] || [];
+    }
+    for (const key in config.data) {
+      if (!(key in config.types)) {
+        delete config.data[key];
+      }
     }
-  }
 
-  setData(data: { [key in T]?: R[] }) {
-    this.data = depPartialUpdate(data, this.data);
+    super({
+      name: "container",
+      attrib: { id: "0", data: config.data },
+      ...config,
+    });
+    this.config = config;
   }
 
   initShape() {
-    const { dom } = this.props;
-    const stage = new Stage({
+    const viewLayer = new Layer();
+    this.stage.add(viewLayer);
+    return viewLayer;
+  }
+
+  init() {
+    const { dom } = this.config;
+    this.stage = new Stage({
       container: dom,
       width: dom.offsetWidth,
       height: dom.offsetHeight,
     });
-
-    this.viewLayer = new Layer();
     this.tempLayer = new Layer();
+    this.stage.add(this.tempLayer);
 
-    stage.add(this.viewLayer, this.tempLayer);
-    return stage;
+    this.initIncFactory();
+    super.init();
   }
 
-  initView() {
-    for (const [key, data] of Object.entries(this.data)) {
-      this.entrys[key] = (data as R[]).map((attrib) => {
-        const entry = new this.props.types[key]({ attrib });
-        entry.init();
-        entry.attachBefore();
-        entry.setParent(this.viewLayer);
-      });
+  initIncFactory() {
+    const types = this.config.types;
+    for (const key in types) {
+      this.incFactorys[key] = incEntitysFactoryGenerate(types[key], this);
     }
   }
 
-  initReactive() {
-    const childDestoryMaps: { [key in string]: () => void } = {};
-    return mergeFuns(
-      watch(
-        () => Object.keys(this.data),
-        (keys, oldKeys) => {
-          const { addPort, delPort } = getChangePart(keys, oldKeys);
-          delPort.forEach((delKey) => {
-            childDestoryMaps[delKey]();
-            this.entrys[delKey] = [];
-          });
+  diffRedraw() {
+    const data = this.attrib.data;
+    const result = {} as {
+      [key in T]: ReturnType<IncEntitysFactory<R, InstanceType<C>>>;
+    };
 
-          addPort.forEach((key) => {
-            const join = attribsJoinEntity(
-              this.data[key],
-              this.props.types[key],
-              null,
-              true,
-              (t) => {
-                setTimeout(() => {
-                  this.viewLayer.add(t.shape);
-                });
-              }
-            );
-            this.entrys[key] = join.entitys;
-            childDestoryMaps[key] = join.destory;
-          });
-        },
-        { immediate: true }
-      ),
-      () => {
-        mergeFuns(Object.values(childDestoryMaps))();
+    for (const key in data) {
+      if (key in this.incFactorys) {
+        result[key] = this.incFactorys[key](data[key]);
       }
+    }
+    return result;
+  }
+
+  initReactive() {
+    return watch(
+      () => {
+        const result = {} as { [key in T]: string[] };
+        for (const key in this.attrib.data) {
+          result[key] = this.attrib.data[key].map(({ id }) => id);
+        }
+        return result;
+      },
+      this.diffRedraw.bind(this),
+      { immediate: true }
     );
   }
 }

+ 34 - 20
src/board/packages/entity.ts

@@ -6,19 +6,22 @@ import { Group } from "konva/lib/Group";
 import { Layer } from "konva/lib/Layer";
 import { Stage } from "konva/lib/Stage";
 import { depPartialUpdate } from "../shared/util";
-import { watchEffect } from "vue";
+import { reactive, watchEffect } from "vue";
 import {
   DragHandlers,
   openShapeDrag,
   openShapeMouseStyles,
 } from "../shared/shape-mose";
 
-export type EntityProps<T extends Attrib> = {
+export type EntityBaseProps = {
+  reactive?: boolean;
+  readonly?: boolean;
+};
+
+export type EntityProps<T extends Attrib> = EntityBaseProps & {
   name?: string;
   attrib: T;
   zIndex?: number;
-  readonly?: boolean;
-  reactive?: boolean;
 };
 
 type ParentShapeType<T extends ShapeType> = T extends Layer
@@ -49,7 +52,12 @@ export abstract class Entity<T extends Attrib, S extends ShapeType> {
   constructor(props: EntityProps<T>) {
     this.name = props.name;
     this.props = props;
+    this.attrib = props.reactive ? (reactive(props.attrib) as T) : props.attrib;
     this.zIndex = props.zIndex || 0;
+
+    if (DEV) {
+      console.log(this.name + " create");
+    }
   }
 
   abstract initShape(): S;
@@ -85,9 +93,7 @@ export abstract class Entity<T extends Attrib, S extends ShapeType> {
   }
 
   setTeleport(tel?: ParentShapeType<S>) {
-    if (this.teleport === tel) {
-      return;
-    } else if (this.shape instanceof Stage) {
+    if (this.shape instanceof Stage) {
       throw "stage 为顶级容器无法挂载到";
     } else if (this.shape instanceof Layer && !(tel instanceof Stage)) {
       throw "layer 只能挂载到 Stage";
@@ -104,10 +110,12 @@ export abstract class Entity<T extends Attrib, S extends ShapeType> {
       const ndx = this.parent.children.indexOf(this as any);
       ~ndx && this.parent.children.splice(ndx, 1);
     }
-    this.parent = parent;
-    if (parent) {
-      this.parent.children.push(this as any);
-      this.setTeleport();
+    if (this.parent !== parent) {
+      this.parent = parent;
+      if (parent) {
+        this.parent.children.push(this as any);
+        this.setTeleport();
+      }
     }
   }
 
@@ -134,25 +142,31 @@ export abstract class Entity<T extends Attrib, S extends ShapeType> {
 
     const parentShape = this.teleport || (this.parent.shape as any);
     const levelShapes = parentShape.children;
-    const beforeShapeNdx =
-      packNdx === 0 ? -1 : levelShapes.indexOf(packChild[packNdx - 1]);
-
-    if (~beforeShapeNdx) {
-      for (let i = beforeShapeNdx + 1; i < levelShapes.length; i++) {
-        parentShape.add(levelShapes[i]);
+    const shapeNdx =
+      packNdx === 0
+        ? 0
+        : levelShapes.indexOf(packChild[packNdx - 1].getShape()) + 1;
+
+    if (shapeNdx !== 0) {
+      let repShape: any = this.shape;
+      for (let i = shapeNdx; i < levelShapes.length; i++) {
+        const temp = levelShapes[i];
+        parentShape.add(repShape);
+        repShape.zIndex(i);
+        repShape = temp;
       }
     } else {
-      parentShape.add(this.shape);
+      this.shape.zIndex(0);
     }
   }
 
   private dragDestory: () => void;
-  enableDrag(draghandler: DragHandlers<S>) {
+  enableDrag<S>(draghandler: DragHandlers<S>) {
     this.disableDrag();
     this.dragDestory = openShapeDrag(this.shape, draghandler);
   }
   disableDrag() {
-    this.dragDestory();
+    this.dragDestory && this.dragDestory();
     this.dragDestory = null;
   }
 

+ 2 - 0
src/board/packages/index.ts

@@ -1 +1,3 @@
 export * from "./whole-line";
+export * from "./container";
+export * from "./entity";

+ 68 - 82
src/board/packages/whole-line/editable/edit-whole-line.ts

@@ -1,99 +1,85 @@
-import { WholeLine, WholeLineLineAttrib, WholeLinePointAttrib } from "../view/";
-import { lineDragStyle, pointDragStyle } from "../style";
-import { mergeFuns } from "../../../../util";
+import {
+  WholeLine,
+  WholeLineLine,
+  WholeLineLineAttrib,
+  WholeLinePoint,
+  WholeLinePointAttrib,
+} from "../view/";
 import {
   getWholeLineLine,
   mergeWholeLinePointsByPoint,
   spliceWholeLineLineByPoint,
 } from "../service";
-import { watchEntitysOpenDrag } from "../../../shared/shape-drag";
+import { EntityDragHandlers, openEntityDrag } from "../../../shared/shape-mose";
 
 export class EditWholeLine extends WholeLine {
-  get points() {
-    return Object.values(this.pointEntitys);
-  }
-
-  get lines() {
-    return Object.values(this.lineEntitys);
-  }
-
-  setPointPositionReady(point: WholeLinePointAttrib) {
-    return [point.x, point.y];
-  }
+  points: WholeLinePoint[];
+  lines: WholeLineLine[];
 
-  setPointPosition(
-    point: WholeLinePointAttrib,
-    move: number[],
-    initPos: number[]
-  ) {
-    point.x = move[0];
-    point.y = move[1];
-  }
+  lineDragHandler: Required<
+    EntityDragHandlers<WholeLineLineAttrib, number[][]>
+  >;
+  pointDragHandler: Required<
+    EntityDragHandlers<WholeLinePointAttrib, number[]>
+  >;
 
-  setPointPositionEnd(point: WholeLinePointAttrib, initPos: number[]) {
-    const merge = mergeWholeLinePointsByPoint(this.attrib, point.id);
-    if (merge)
-      spliceWholeLineLineByPoint(this.attrib, merge?.info.main.id || point.id);
-  }
-
-  setLinePositionReady(line: WholeLineLineAttrib) {
-    return getWholeLineLine(this.attrib, line.id).map(({ x, y }) => [x, y]);
+  diffRedraw() {
+    const inc = super.diffRedraw();
+    inc.lineEntityInc.adds.forEach((line) => {
+      openEntityDrag(line, this.lineDragHandler);
+    });
+    inc.pointEntityInc.adds.forEach((point) => {
+      openEntityDrag(point, this.pointDragHandler);
+    });
+    return inc;
   }
 
-  setLinePosition(
-    line: WholeLineLineAttrib,
-    move: number[],
-    initPositions: number[][]
-  ) {
-    const points = getWholeLineLine(this.attrib, line.id);
-    const currentPositions = initPositions.map((pos) => [
-      pos[0] + move[0],
-      pos[1] + move[1],
-    ]);
+  init() {
+    this.lineDragHandler = {
+      readyHandler: (lineAttrib) => {
+        const pointAttribs = getWholeLineLine(this.attrib, lineAttrib.id);
+        return pointAttribs.map(({ x, y }) => [x, y]);
+      },
+      moveHandler: (lineAttrib, move, initPositions) => {
+        const points = getWholeLineLine(this.attrib, lineAttrib.id);
 
-    this.setPointPosition(points[0], currentPositions[0], initPositions[0]);
-    this.setPointPosition(points[1], currentPositions[1], initPositions[1]);
-  }
+        const currentPositions = initPositions.map((pos) => [
+          pos[0] + move[0],
+          pos[1] + move[1],
+        ]);
 
-  setLinePositionEnd(line: WholeLineLineAttrib, initPositions: number[][]) {
-    const points = getWholeLineLine(this.attrib, line.id);
-    this.setPointPositionEnd(points[0], initPositions[0]);
-    this.setPointPositionEnd(points[1], initPositions[1]);
-  }
+        this.pointDragHandler.moveHandler(
+          points[0],
+          currentPositions[0],
+          initPositions[0]
+        );
+        this.pointDragHandler.moveHandler(
+          points[1],
+          currentPositions[1],
+          initPositions[1]
+        );
+      },
+      endHandler: (lineAttrib, initPositions) => {
+        const points = getWholeLineLine(this.attrib, lineAttrib.id);
+        this.pointDragHandler.endHandler(points[0], initPositions[0]);
+        this.pointDragHandler.endHandler(points[1], initPositions[1]);
+      },
+    };
 
-  private stopWatchs: (() => void)[] = [];
-  init() {
-    setTimeout(() => {
-      mergeWholeLinePointsByPoint(this.attrib, "23");
-    });
+    this.pointDragHandler = {
+      readyHandler: ({ x, y }) => [x, y],
+      moveHandler: (pointAttrib, move) => {
+        pointAttrib.x = move[0];
+        pointAttrib.y = move[1];
+      },
+      endHandler: (pointAttrib) => {
+        const merge = mergeWholeLinePointsByPoint(this.attrib, pointAttrib.id);
+        spliceWholeLineLineByPoint(
+          this.attrib,
+          merge?.info.main.id || pointAttrib.id
+        );
+      },
+    };
     super.init();
-
-    this.stopWatchs.push(
-      // 点位拖拽监听
-      watchEntitysOpenDrag(
-        () => Object.values(this.pointEntitys),
-        {
-          readyHandler: this.setPointPositionReady.bind(this),
-          moveHandler: this.setPointPosition.bind(this),
-          endHandler: this.setPointPositionEnd.bind(this),
-        },
-        pointDragStyle
-      ),
-      // 监听线段拖拽
-      watchEntitysOpenDrag(
-        () => Object.values(this.lineEntitys),
-        {
-          readyHandler: this.setLinePositionReady.bind(this),
-          moveHandler: this.setLinePosition.bind(this),
-          endHandler: this.setLinePositionEnd.bind(this),
-        },
-        lineDragStyle
-      )
-    );
-  }
-
-  destory() {
-    super.destory();
-    mergeFuns(...this.stopWatchs)();
   }
 }

+ 61 - 74
src/board/packages/whole-line/helper/whole-line-line-helper.ts

@@ -1,22 +1,25 @@
 import konva from "konva";
-import { PackageBase, PackageBaseProps } from "../../../shared/package-base";
-import { TArrow, TGroup, TLabel, TText } from "../../../type";
-import { WholeLineLineAttrib } from "../view/whole-line-line";
-import { watch } from "vue";
+import {
+  WholeLineLineAttrib,
+  WholeLineLineProps,
+} from "../view/whole-line-line";
 import { getLineDireAngle } from "../../../shared/math";
 import { MathUtils } from "three";
 import { WholeLineAttrib } from "../view/whole-line";
 import { lineHelperZIndex } from "../style";
+import { Entity } from "../../entity";
+import { Group } from "konva/lib/Group";
+import { Label } from "konva/lib/shapes/Label";
+import { Arrow } from "konva/lib/shapes/Arrow";
+import { Text } from "konva/lib/shapes/Text";
 
-export class PolygonLineHelper extends PackageBase<
-  WholeLineLineAttrib,
-  TGroup
-> {
+export class WholeLineLineHelper extends Entity<WholeLineLineAttrib, Group> {
+  static namespace = "line-helper";
   private config: WholeLineAttrib;
 
-  constructor(props: PackageBaseProps<WholeLineLineAttrib>) {
+  constructor(props: WholeLineLineProps) {
     props.zIndex = props.zIndex || lineHelperZIndex;
-    props.name = props.name || "line-helper" + props.attrib.id;
+    props.name = props.name || WholeLineLineHelper.namespace + props.attrib.id;
     super(props);
   }
 
@@ -86,77 +89,61 @@ export class PolygonLineHelper extends PackageBase<
     return shape;
   }
 
-  initReactive() {
-    return watch(
-      () => {
-        const points = this.attrib.pointIds.map((id) =>
-          this.config.points.find((point) => point.id === id)
-        );
-        if (points.some((point) => !point)) {
-          return null;
-        }
+  diffRedraw(): void {
+    const points = this.attrib.pointIds.map((id) =>
+      this.config.points.find((point) => point.id === id)
+    );
+    if (points.some((point) => !point)) {
+      return null;
+    }
 
-        let twoWay = false;
-        const labels: string[] = [];
-        for (const polygon of this.config.polygons) {
-          for (const lineId of polygon.lineIds) {
-            const line = this.config.lines.find(({ id }) => id === lineId);
-            if (
-              line.pointIds.includes(this.attrib.pointIds[0]) &&
-              line.pointIds.includes(this.attrib.pointIds[1])
-            ) {
-              labels.push(`${line.id} [${line.pointIds.join(",")}]`);
+    let twoWay = false;
+    const labels: string[] = [];
+    for (const polygon of this.config.polygons) {
+      for (const lineId of polygon.lineIds) {
+        const line = this.config.lines.find(({ id }) => id === lineId);
+        if (
+          line.pointIds.includes(this.attrib.pointIds[0]) &&
+          line.pointIds.includes(this.attrib.pointIds[1])
+        ) {
+          labels.push(`${line.id} [${line.pointIds.join(",")}]`);
 
-              twoWay = twoWay || line.pointIds[0] === this.attrib.pointIds[1];
-            }
-          }
+          twoWay = twoWay || line.pointIds[0] === this.attrib.pointIds[1];
         }
+      }
+    }
 
-        const coords: number[] = [];
-        points.forEach(({ x, y }, ndx) => {
-          coords[ndx * 2] = x;
-          coords[ndx * 2 + 1] = y;
-        });
-        return {
-          twoWay,
-          label: labels.join(" | "),
-          coords: coords,
-        };
-      },
-      (data) => {
-        if (!data) return;
-        if (!data.label) {
-          console.log(this.attrib);
-        }
+    const coords: number[] = [];
+    points.forEach(({ x, y }, ndx) => {
+      coords[ndx * 2] = x;
+      coords[ndx * 2 + 1] = y;
+    });
 
-        const angle = MathUtils.radToDeg(getLineDireAngle(data.coords, [0, 1]));
-        this.shape
-          .findOne<TLabel>(".label")
-          .x((data.coords[0] + data.coords[2]) / 2)
-          .y((data.coords[1] + data.coords[3]) / 2)
-          .rotation(angle < 0 ? angle + 90 : angle - 90);
+    const angle = MathUtils.radToDeg(getLineDireAngle(coords, [0, 1]));
+    this.shape
+      .findOne<Label>(".label")
+      .x((coords[0] + coords[2]) / 2)
+      .y((coords[1] + coords[3]) / 2)
+      .rotation(angle < 0 ? angle + 90 : angle - 90);
 
-        this.shape
-          .findOne<TArrow>(".arrow-1")
-          .x(data.coords[2])
-          .y(data.coords[3])
-          .rotation(angle + 90)
-          .visible(true);
+    this.shape
+      .findOne<Arrow>(".arrow-1")
+      .x(coords[2])
+      .y(coords[3])
+      .rotation(angle + 90)
+      .visible(true);
 
-        if (data.twoWay) {
-          this.shape
-            .findOne<TArrow>(".arrow-2")
-            .x(data.coords[0])
-            .y(data.coords[1])
-            .rotation(angle - 90)
-            .visible(true);
-        } else {
-          this.shape.findOne<TArrow>(".arrow-2").visible(false);
-        }
+    if (twoWay) {
+      this.shape
+        .findOne<Arrow>(".arrow-2")
+        .x(coords[0])
+        .y(coords[1])
+        .rotation(angle - 90)
+        .visible(true);
+    } else {
+      this.shape.findOne<Arrow>(".arrow-2").visible(false);
+    }
 
-        this.shape.findOne<TText>(".text").text(data.label);
-      },
-      { immediate: true }
-    );
+    this.shape.findOne<Text>(".text").text(labels.join(" | "));
   }
 }

+ 13 - 18
src/board/packages/whole-line/helper/whole-line-point-helper.ts

@@ -1,17 +1,18 @@
 import konva from "konva";
-import { PackageBase, PackageBaseProps } from "../../../shared/package-base";
-import { TLabel } from "../../../type";
-import { watch } from "vue";
-import { WholeLinePointAttrib } from "../view/whole-line-point";
+import {
+  WholeLinePointAttrib,
+  WholeLinePointProps,
+} from "../view/whole-line-point";
 import { pointHelperZIndex } from "../style";
+import { Entity } from "../../entity";
+import { Label } from "konva/lib/shapes/Label";
 
-export class WholeLinePointHelper extends PackageBase<
-  WholeLinePointAttrib,
-  TLabel
-> {
-  constructor(props: PackageBaseProps<WholeLinePointAttrib>) {
+export class WholeLinePointHelper extends Entity<WholeLinePointAttrib, Label> {
+  static namespace = "point-helper";
+
+  constructor(props: WholeLinePointProps) {
     props.zIndex = props.zIndex || pointHelperZIndex;
-    props.name = props.name || "line-helper" + props.attrib.id;
+    props.name = props.name || WholeLinePointHelper.namespace + props.attrib.id;
     super(props);
   }
 
@@ -43,13 +44,7 @@ export class WholeLinePointHelper extends PackageBase<
     return label;
   }
 
-  initReactive() {
-    return watch(
-      this.attrib,
-      (data) => {
-        this.shape.x(data.x).y(data.y);
-      },
-      { immediate: true, deep: true }
-    );
+  diffRedraw(): void {
+    this.shape.x(this.attrib.x).y(this.attrib.y);
   }
 }

+ 2 - 2
src/board/packages/whole-line/style.ts

@@ -32,7 +32,7 @@ export const lineDragStyle = {
   },
 };
 
-export const pointZIndex = 30;
+export const pointZIndex = 3;
 export const lineZIndex = 1;
-export const lineHelperZIndex = 8;
+export const lineHelperZIndex = 2;
 export const pointHelperZIndex = 4;

+ 1 - 14
src/board/packages/whole-line/view/whole-line-polygon.ts

@@ -1,18 +1,5 @@
-import { Attrib, TGroup } from "../../../type";
-import { PackageBase } from "../../../shared/package-base";
-import { Group } from "konva/lib/Group";
+import { Attrib } from "../../../type";
 
 export type WholeLinePolygonAttrib = Attrib & {
   lineIds: string[];
 };
-
-export class WholeLinePolygon extends PackageBase<
-  WholeLinePolygonAttrib,
-  TGroup
-> {
-  static namespace = "polygon";
-
-  initShape() {
-    return new Group({ id: this.name });
-  }
-}

+ 67 - 99
src/board/packages/whole-line/view/whole-line.ts

@@ -1,18 +1,16 @@
 import { Attrib } from "../../../type";
-import { mergeFuns } from "../../../../util";
-import { attribsJoinEntity, partialComputed } from "../../../shared/util";
 import { DEV } from "../../../env";
-import { WholeLinePointHelper } from "../helper";
+import { WholeLinePointHelper, WholeLineLineHelper } from "../helper";
 import { WholeLinePoint, WholeLinePointAttrib } from "./whole-line-point";
 import { WholeLineLine, WholeLineLineAttrib } from "./whole-line-line";
 import { WholeLinePolygonAttrib } from "./whole-line-polygon";
-import { PolygonLineHelper } from "../helper/whole-line-line-helper";
 import { Group } from "konva/lib/Group";
 import { Entity, EntityProps } from "../../entity";
 import {
   IncEntitysFactory,
   incEntitysFactoryGenerate,
 } from "../../../shared/entity-utils";
+import { watch } from "vue";
 
 export type WholeLineAttrib = Attrib & {
   points: WholeLinePointAttrib[];
@@ -23,131 +21,101 @@ export type WholeLineAttrib = Attrib & {
 export type WholeLineProps = EntityProps<WholeLineAttrib>;
 
 export class WholeLine extends Entity<WholeLineAttrib, Group> {
+  static namespace = "whole-line";
+
+  private incLinesHelperFactory: IncEntitysFactory<
+    WholeLineLineAttrib,
+    WholeLineLineHelper
+  >;
   private incLinesFactory: IncEntitysFactory<
     WholeLineLineAttrib,
     WholeLineLine
   >;
+
+  private incPointsHelperFactory?: IncEntitysFactory<
+    WholeLinePointAttrib,
+    WholeLinePointHelper
+  >;
   private incPointsFactory: IncEntitysFactory<
     WholeLinePointAttrib,
     WholeLinePoint
   >;
 
   constructor(props: WholeLineProps) {
-    props.name = props.name || "whole-line" + props.attrib.id;
+    props.name = props.name || WholeLine.namespace + props.attrib.id;
     super(props);
+  }
 
+  initIncFactory() {
     this.incLinesFactory = incEntitysFactoryGenerate(
       WholeLineLine,
       this,
       (line) => line.setConfig(this.attrib)
     );
-    this.incPointsFactory = incEntitysFactoryGenerate(WholeLinePoint, this);
-  }
-
-  pointEntitys: Record<string, WholeLinePoint>;
-  lineEntitys: Record<string, WholeLineLine>;
-
-  initShape() {
-    return new Group({ id: this.name });
-  }
-
-  diffRedraw(): void {
-    this.incLinesFactory(this.attrib.lines);
-    this.incPointsFactory(this.attrib.points);
-
-    this.attrib.points.forEach((point) => {
-      const wPoint = new WholeLinePoint({
-        attrib: point,
-        readonly: true,
-      });
-      wPoint.init();
-      this.pointEntitys[wPoint.name] = wPoint;
-      this.shape.add(wPoint.shape);
-    });
-
-    this.attrib.lines.forEach((line) => {
-      const wLine = new WholeLineLine({
-        attrib: line,
-        readonly: true,
-      });
-      wLine.setConfig(this.attrib);
-      wLine.init();
-      this.lineEntitys[wLine.name] = wLine;
-      this.shape.add(wLine.shape);
+    this.incLinesHelperFactory =
+      DEV &&
+      incEntitysFactoryGenerate(WholeLineLineHelper, this, (line) =>
+        line.setConfig(this.attrib)
+      );
 
-      return wLine;
-    });
+    this.incPointsFactory = incEntitysFactoryGenerate(WholeLinePoint, this);
+    this.incPointsHelperFactory =
+      DEV && incEntitysFactoryGenerate(WholeLinePointHelper, this);
   }
 
   init() {
+    this.initIncFactory();
     super.init();
   }
 
-  initReactive() {
-    const unReactives: (() => void)[] = [];
+  initShape() {
+    return new Group({ id: this.name });
+  }
 
-    const lineAttribsComputed = partialComputed(() => {
-      // 去重 防止来回线段绘画两次
-      const lines: WholeLineLineAttrib[] = [];
-      for (let i = this.attrib.lines.length - 1; i >= 0; i--) {
-        const a = this.attrib.lines[i];
-        let j = 0;
-        for (j = 0; j < i; j++) {
-          const b = this.attrib.lines[j];
-          if (
-            b.pointIds.includes(a.pointIds[0]) &&
-            b.pointIds.includes(a.pointIds[1])
-          ) {
-            break;
-          }
-        }
-        if (i === j) {
-          lines.push(a);
+  getRedrawLines() {
+    // 去重 防止来回线段绘画两次
+    const lines: WholeLineLineAttrib[] = [];
+    for (let i = this.attrib.lines.length - 1; i >= 0; i--) {
+      const a = this.attrib.lines[i];
+      let j = 0;
+      for (j = 0; j < i; j++) {
+        const b = this.attrib.lines[j];
+        if (
+          b.pointIds.includes(a.pointIds[0]) &&
+          b.pointIds.includes(a.pointIds[1])
+        ) {
+          break;
         }
       }
-      return lines;
-    });
-    unReactives.push(lineAttribsComputed.stop);
-
-    const pointJoin = attribsJoinEntity(
-      this.attrib.points,
-      WholeLinePoint,
-      this,
-      true
-    );
-    unReactives.push(pointJoin.destory);
-    this.pointEntitys = pointJoin.entitys;
-    pointJoin.entitys[0];
-
-    const lineJoin = attribsJoinEntity(
-      lineAttribsComputed.data,
-      WholeLineLine,
-      this,
-      true,
-      (line) => line.setConfig(this.attrib)
-    );
-    unReactives.push(lineJoin.destory);
-    this.lineEntitys = lineJoin.entitys;
+      if (i === j) {
+        lines.push(a);
+      }
+    }
+    return lines;
+  }
 
+  diffRedraw() {
+    const lineAttribs = this.getRedrawLines();
     if (DEV) {
-      const pointHelperJoin = attribsJoinEntity(
-        this.attrib.points,
-        WholeLinePointHelper,
-        this,
-        true
-      );
-      unReactives.push(pointHelperJoin.destory);
-
-      const lineHelperJoin = attribsJoinEntity(
-        lineAttribsComputed.data,
-        PolygonLineHelper,
-        this,
-        true,
-        (h) => h.setConfig(this.attrib)
-      );
-      unReactives.push(lineHelperJoin.destory);
+      this.incLinesHelperFactory(lineAttribs);
+      this.incPointsHelperFactory(this.attrib.points);
     }
+    const lineEntityInc = this.incLinesFactory(lineAttribs);
+    const pointEntityInc = this.incPointsFactory(this.attrib.points);
+    return { lineEntityInc, pointEntityInc };
+  }
 
-    return mergeFuns(...unReactives);
+  initReactive() {
+    return watch(
+      () => ({
+        pointIds: this.attrib.points.map(({ id }) => id),
+        lineIds: this.attrib.lines.map(({ id }) => id),
+      }),
+      (newData) => {
+        console.log(newData);
+        this.diffRedraw();
+      },
+      { immediate: true }
+    );
   }
 }

+ 18 - 8
src/board/register.ts

@@ -1,25 +1,35 @@
-import { shallowReadonly } from "vue";
-import { Attrib, EntityClass } from "./type";
+import { Attrib, ShapeType } from "./type";
 import { Container } from "./packages/container";
+import { EntityType } from "./packages";
 
-export const register = <T extends string, R extends Attrib>(types: {
-  [key in T]: EntityClass<R>;
+export const register = <
+  T extends string,
+  R extends Attrib,
+  S extends ShapeType
+>(types: {
+  [key in T]: EntityType<R, S>;
 }) => {
-  const initBoard = (dom: HTMLDivElement, data?: { [key in T]?: R[] }) => {
+  const initBoard = (
+    dom: HTMLDivElement,
+    data?: { [key in T]?: R[] },
+    readonly = false
+  ) => {
     const container = new Container({
       dom,
+      readonly,
       types,
       data,
+      reactive: !readonly,
     });
     container.init();
 
     return {
-      stage: container,
+      tree: container,
       setData(newData: { [key in T]?: R[] }) {
-        container.setData(newData);
+        container.setAttrib({ data: newData });
       },
       getData() {
-        return shallowReadonly(container.data);
+        return container.attrib.data;
       },
       destory() {
         container.destory();

+ 14 - 3
src/board/shared/entity-utils.ts

@@ -2,6 +2,15 @@ import { EntityType, Entity } from "../packages/entity";
 import { Attrib, ShapeType } from "../type";
 import { getChangeAllPoart } from "./util";
 
+const getExtendsProps = (parent: Entity<any, any>) => {
+  return parent
+    ? {
+        reactive: parent.props.reactive,
+        readonly: parent.props.reactive,
+      }
+    : {};
+};
+
 export const entityFactory = <
   T extends Attrib,
   S extends ShapeType,
@@ -12,8 +21,10 @@ export const entityFactory = <
   parent?: Entity<any, any>,
   extra?: (self: InstanceType<C>) => void
 ) => {
-  const entity = new Type({ attrib }) as InstanceType<C>;
-  extra(entity);
+  const entity = new Type({
+    attrib,
+    ...getExtendsProps(parent),
+  }) as InstanceType<C>;
   extra && extra(entity);
   entity.init();
   entity.setParent(parent);
@@ -66,7 +77,7 @@ export const incEntitysFactoryGenerate = <
       return cache[id];
     });
 
-    oldAttribs = attribs;
+    oldAttribs = [...attribs];
     return {
       adds,
       dels,

+ 0 - 160
src/board/shared/package-base.ts

@@ -1,160 +0,0 @@
-import konva from "konva";
-import { Attrib, GetSetPick, TGroup, TShape } from "../type";
-import { DragResult, injectDrag } from "./shape-drag";
-import { DEV } from "../env";
-
-const empty = () => {};
-
-export type PackageBaseProps<T extends Attrib> = {
-  name?: string;
-  attrib: T;
-  zIndex?: number;
-  readonly?: boolean;
-};
-export abstract class PackageBase<T extends Attrib, S extends TShape | TGroup> {
-  attrib: T;
-  shape: S;
-  name: string;
-  drag: DragResult | null;
-  readonly: boolean;
-
-  private zIndex: number;
-  children: PackageBase<Attrib, TGroup | TShape>[] = [];
-  parent: PackageBase<Attrib, TGroup | TShape>;
-
-  protected destoryReactive: () => void;
-
-  constructor(props: PackageBaseProps<T>) {
-    this.name = props.name;
-    this.attrib = props.attrib;
-    this.drag = null;
-    this.zIndex = props.zIndex || 0;
-    this.readonly = props.readonly || false;
-  }
-
-  init() {
-    this.shape = this.initShape();
-    this.shape.id(this.name);
-    if (this.readonly) {
-      this.initView();
-    } else {
-      this.destoryReactive = this.initReactive();
-    }
-  }
-
-  getSameLevelNdx(parent = this.parent) {
-    const sameLevel = parent.children;
-
-    for (let i = sameLevel.length - 1; i >= 0; i--) {
-      if (sameLevel[i] !== this && sameLevel[i].zIndex <= this.zIndex) {
-        return i + 1;
-      }
-    }
-    return 0;
-  }
-
-  setParent(parent: PackageBase<Attrib, TGroup> | null) {
-    const child = this as any;
-
-    if (this.parent) {
-      const ndx = this.parent.children.indexOf(child);
-      ~ndx && this.parent.children.splice(ndx, 1);
-    }
-    this.parent = parent;
-    if (parent) {
-      this.parent.children.push(child);
-
-      const parentShape = this.parent.shape as TGroup;
-      parentShape.add(this.shape);
-      this.setZIndex(child.zIndex);
-    }
-  }
-
-  setZIndex(index: number) {
-    this.zIndex = index;
-    const packNdx = this.getSameLevelNdx();
-    const packChild = this.parent.children;
-    let repPack: any = this;
-    for (let i = packNdx; i < packChild.length; i++) {
-      const temp = packChild[i];
-      packChild[i] = repPack;
-      repPack = temp;
-    }
-    this.shape.zIndex(packNdx);
-  }
-
-  childrenShapesSort() {
-    if (!(this.shape instanceof konva.Group)) {
-      return;
-    }
-    const shapes = this.shape.children;
-    const indexs = shapes.map((_, i) => i);
-
-    this.children.forEach((child) => {
-      const ndx = shapes.indexOf(child.getShape());
-      if (~ndx) {
-        indexs[ndx] = indexs.length + child.zIndex;
-      }
-    });
-    for (let i = 0; i < shapes.length; i++) {
-      shapes[i].zIndex(indexs[i]);
-    }
-  }
-
-  abstract initShape(): S;
-
-  enableDrag(pointDragStyle: {
-    hover?: GetSetPick<S> | (() => void);
-    active?: GetSetPick<S> | (() => void);
-    dragend?: () => void;
-    dragstart?: () => void;
-  }) {
-    this.drag && this.drag.destory();
-    this.drag = injectDrag(this.shape, pointDragStyle);
-  }
-
-  disableDrag() {
-    this.drag?.destory();
-    this.drag = null;
-  }
-
-  setAttrib(newAttrib: T) {
-    this.attrib = newAttrib;
-    console.log("setAttrib 重建", this.name);
-    this.destoryReactive && this.destoryReactive();
-    this.initReactive();
-  }
-
-  needUpdate(newAttrib: T) {
-    return newAttrib !== this.attrib;
-  }
-
-  initReactive() {
-    return empty;
-  }
-
-  initView() {}
-
-  getShape() {
-    return this.shape;
-  }
-
-  destory() {
-    this.setParent(null);
-    this.destoryReactive && this.destoryReactive();
-    this.drag?.destory();
-    if (DEV) {
-      console.log(this.name, "destory");
-    }
-    if (this.shape instanceof konva.Group) {
-      this.shape.destroyChildren();
-    } else {
-      this.shape.destroy();
-    }
-  }
-}
-
-export type PackageBaseType<T extends Attrib, S extends TShape | TGroup> = new (
-  name: string,
-  attrib: T
-) => PackageBase<T, S>;

+ 0 - 194
src/board/shared/shape-drag.ts

@@ -1,194 +0,0 @@
-import { reactive, ref, watch } from "vue";
-import { Attrib, GetSetPick, TGroup, TShape } from "../type";
-import { getChangePart, setShapeConfig } from "./util";
-import { PackageBase } from "./package-base";
-
-export const injectDrag = <T extends TShape | TGroup>(
-  shape: T,
-  styles?: {
-    hover?: GetSetPick<T> | (() => void);
-    active?: GetSetPick<T> | (() => void);
-    dragend?: () => void;
-    dragstart?: () => void;
-  },
-  rangeCheck?: (pos: number[]) => boolean
-) => {
-  shape.draggable(true);
-  shape.listening(true);
-
-  const position = reactive([shape.x(), shape.y()]);
-  shape.dragBoundFunc((pos) => {
-    if (rangeCheck && rangeCheck([pos.x, pos.y])) {
-      return pos;
-    } else {
-      position[0] = pos.x;
-      position[1] = pos.y;
-      return shape.absolutePosition();
-    }
-  });
-
-  const keys = new Set<string>();
-
-  const draging = ref(false);
-  let enter = false;
-  const enterHandler = (ev) => {
-    if (styles.hover instanceof Function) {
-      styles.hover();
-    } else {
-      setShapeConfig(shape, styles.hover);
-      const canvas = ev.evt.toElement as HTMLCanvasElement;
-      canvas && (canvas.style.cursor = "pointer");
-    }
-  };
-  const dragingHandler = () => {
-    if (styles.active instanceof Function) {
-      styles.active();
-    } else {
-      setShapeConfig(shape, styles.active);
-    }
-  };
-  const cancelHandler = (ev) => {
-    if (!draging.value && !enter) {
-      setShapeConfig(shape, pubStyle as any);
-      const canvas = ev.evt.toElement as HTMLCanvasElement;
-      canvas && (canvas.style.cursor = "inherit");
-    } else if (draging.value) {
-      dragingHandler();
-    } else if (enter) {
-      enterHandler(ev);
-    }
-  };
-
-  if (styles.hover) {
-    if (!(styles.hover instanceof Function)) {
-      Object.keys(styles.hover).forEach((key) => keys.add(key));
-    }
-    shape.on("mouseenter.drag", (ev) => {
-      enter = true;
-      enterHandler(ev);
-    });
-
-    shape.on("mouseleave.drag", (ev) => {
-      enter = false;
-      cancelHandler(ev);
-    });
-  }
-
-  if (styles.active) {
-    if (!(styles.active instanceof Function)) {
-      Object.keys(styles.active).forEach((key) => keys.add(key));
-    }
-    shape.on("dragstart.drag mousedown.drag", () => {
-      draging.value = true;
-      dragingHandler();
-    });
-  }
-
-  if (keys.size > 0 || "dragend" in styles) {
-    shape.on("mouseup.drag dragend.drag", (ev) => {
-      draging.value = false;
-      cancelHandler(ev);
-    });
-  }
-  if (styles.dragend) {
-    shape.on("dragend.drag", () => {
-      styles.dragend();
-    });
-  }
-  if (styles.dragstart) {
-    shape.on("dragstart.drag", () => {
-      styles.dragstart();
-    });
-  }
-
-  const pubStyle = Object.fromEntries(
-    [...keys.values()].map((key) => [key, shape[key]()])
-  );
-
-  return {
-    position,
-    draging,
-    destory: () => {
-      shape.listening(false);
-      shape.draggable(false);
-      shape.off(
-        "mouseup.drag dragend.drag dragstart.drag mousedown.drag mouseleave.drag mouseenter.drag"
-      );
-    },
-  };
-};
-
-export type DragResult = ReturnType<typeof injectDrag<TShape | TGroup>>;
-
-type DragWatchandlers<T, K extends Attrib> = {
-  readyHandler: (attrib: K) => T;
-  moveHandler: (attrib: K, move: number[], readyData: T) => void;
-  endHandler: (attrib: K, readyData: T) => void;
-};
-export const entityOpenDrag = <T, K extends Attrib, S extends TShape | TGroup>(
-  entity: PackageBase<K, S>,
-  handlers: DragWatchandlers<T, K>,
-  styles: {
-    hover?: GetSetPick<S> | (() => void);
-    active?: GetSetPick<S> | (() => void);
-  }
-) => {
-  let readlyData: T;
-
-  const moveReadly = () => (readlyData = handlers.readyHandler(entity.attrib));
-  const move = (pos: number[]) =>
-    handlers.moveHandler(entity.attrib, pos, readlyData);
-  const moveEnd = () => handlers.endHandler(entity.attrib, readlyData);
-  const dragArgs = {
-    ...styles,
-    dragstart: moveReadly,
-    dragend: moveEnd,
-  };
-
-  entity.enableDrag(dragArgs);
-
-  const stopDragWatch = watch(() => [...entity.drag.position], move);
-
-  return () => {
-    entity.disableDrag();
-    stopDragWatch();
-  };
-};
-
-export const watchEntitysOpenDrag = <
-  T,
-  K extends Attrib,
-  S extends TShape | TGroup
->(
-  getter: () => PackageBase<K, S>[],
-  handlers: DragWatchandlers<T, K>,
-  styles: {
-    hover?: GetSetPick<S> | (() => void);
-    active?: GetSetPick<S> | (() => void);
-  }
-) => {
-  const dragWatchStopMap = new WeakMap<PackageBase<K, S>, () => void>();
-  const entryDragStop = (entry: PackageBase<K, S>) => {
-    const f = dragWatchStopMap.get(entry);
-    f && f();
-  };
-  let currentEntrys: PackageBase<K, S>[] = [];
-
-  const stopWatch = watch(
-    getter,
-    (newEntrys, oldEntrys) => {
-      const { addPort, delPort } = getChangePart(newEntrys, oldEntrys);
-      delPort.forEach(entryDragStop);
-      addPort.forEach((entry) => {
-        dragWatchStopMap.set(entry, entityOpenDrag(entry, handlers, styles));
-      });
-      currentEntrys = newEntrys;
-    },
-    { immediate: true, flush: "pre" }
-  );
-
-  return () => {
-    stopWatch();
-    currentEntrys.forEach(entryDragStop);
-  };
-};

+ 24 - 192
src/board/shared/shape-mose.ts

@@ -1,9 +1,10 @@
-import { reactive, ref, watch } from "vue";
-import { Attrib, GetSetPick, ShapeStyles, TGroup, TShape } from "../type";
-import { getChangePart, setShapeConfig } from "./util";
-import { PackageBase } from "./package-base";
+import { Attrib, ShapeStyles, ShapeType } from "../type";
+import { setShapeConfig } from "./util";
+import { Entity } from "../packages/entity";
+import { Shape } from "konva/lib/Shape";
+import { Group } from "konva/lib/Group";
 
-export const openShapeMouseStyles = <T extends TShape | TGroup>(
+export const openShapeMouseStyles = <T extends Shape | Group>(
   shape: T,
   styles?: ShapeStyles<T>,
   namespace = "mouse-style"
@@ -89,7 +90,7 @@ export type DragHandlers<T> = {
   endHandler?: (readyData: T) => void;
 };
 
-export const openShapeDrag = <T extends TShape | TGroup, D>(
+export const openShapeDrag = <T extends Shape | Group, D>(
   shape: T,
   handler: DragHandlers<D>
 ) => {
@@ -118,193 +119,24 @@ export const openShapeDrag = <T extends TShape | TGroup, D>(
   };
 };
 
-export const injectDrag = <T extends TShape | TGroup>(
-  shape: T,
-  styles?: {
-    hover?: GetSetPick<T> | (() => void);
-    active?: GetSetPick<T> | (() => void);
-    dragend?: () => void;
-    dragstart?: () => void;
-  },
-  rangeCheck?: (pos: number[]) => boolean
-) => {
-  shape.draggable(true);
-
-  shape.listening(true);
-
-  const position = reactive([shape.x(), shape.y()]);
-  shape.dragBoundFunc((pos) => {
-    if (rangeCheck && rangeCheck([pos.x, pos.y])) {
-      return pos;
-    } else {
-      position[0] = pos.x;
-      position[1] = pos.y;
-      return shape.absolutePosition();
-    }
-  });
-
-  const keys = new Set<string>();
-
-  const draging = ref(false);
-  let enter = false;
-  const enterHandler = (ev) => {
-    if (styles.hover instanceof Function) {
-      styles.hover();
-    } else {
-      setShapeConfig(shape, styles.hover);
-      const canvas = ev.evt.toElement as HTMLCanvasElement;
-      canvas && (canvas.style.cursor = "pointer");
-    }
-  };
-  const dragingHandler = () => {
-    if (styles.active instanceof Function) {
-      styles.active();
-    } else {
-      setShapeConfig(shape, styles.active);
-    }
-  };
-  const cancelHandler = (ev) => {
-    if (!draging.value && !enter) {
-      setShapeConfig(shape, pubStyle as any);
-      const canvas = ev.evt.toElement as HTMLCanvasElement;
-      canvas && (canvas.style.cursor = "inherit");
-    } else if (draging.value) {
-      dragingHandler();
-    } else if (enter) {
-      enterHandler(ev);
-    }
-  };
-
-  if (styles.hover) {
-    if (!(styles.hover instanceof Function)) {
-      Object.keys(styles.hover).forEach((key) => keys.add(key));
-    }
-    shape.on("mouseenter.drag", (ev) => {
-      enter = true;
-      enterHandler(ev);
-    });
-
-    shape.on("mouseleave.drag", (ev) => {
-      enter = false;
-      cancelHandler(ev);
-    });
-  }
-
-  if (styles.active) {
-    if (!(styles.active instanceof Function)) {
-      Object.keys(styles.active).forEach((key) => keys.add(key));
-    }
-    shape.on("dragstart.drag mousedown.drag", () => {
-      draging.value = true;
-      dragingHandler();
-    });
-  }
-
-  if (keys.size > 0 || "dragend" in styles) {
-    shape.on("mouseup.drag dragend.drag", (ev) => {
-      draging.value = false;
-      cancelHandler(ev);
-    });
-  }
-  if (styles.dragend) {
-    shape.on("dragend.drag", () => {
-      styles.dragend();
-    });
-  }
-  if (styles.dragstart) {
-    shape.on("dragstart.drag", () => {
-      styles.dragstart();
-    });
-  }
-
-  const pubStyle = Object.fromEntries(
-    [...keys.values()].map((key) => [key, shape[key]()])
-  );
-
-  return {
-    position,
-    draging,
-    destory: () => {
-      shape.listening(false);
-      shape.draggable(false);
-      shape.off(
-        "mouseup.drag dragend.drag dragstart.drag mousedown.drag mouseleave.drag mouseenter.drag"
-      );
-    },
-  };
-};
-
-export type DragResult = ReturnType<typeof injectDrag<TShape | TGroup>>;
-
-type DragWatchandlers<T, K extends Attrib> = {
-  readyHandler: (attrib: K) => T;
-  moveHandler: (attrib: K, move: number[], readyData: T) => void;
-  endHandler: (attrib: K, readyData: T) => void;
-};
-export const entityOpenDrag = <T, K extends Attrib, S extends TShape | TGroup>(
-  entity: PackageBase<K, S>,
-  handlers: DragWatchandlers<T, K>,
-  styles: {
-    hover?: GetSetPick<S> | (() => void);
-    active?: GetSetPick<S> | (() => void);
-  }
-) => {
-  let readlyData: T;
-
-  const moveReadly = () => (readlyData = handlers.readyHandler(entity.attrib));
-  const move = (pos: number[]) =>
-    handlers.moveHandler(entity.attrib, pos, readlyData);
-  const moveEnd = () => handlers.endHandler(entity.attrib, readlyData);
-  const dragArgs = {
-    ...styles,
-    dragstart: moveReadly,
-    dragend: moveEnd,
-  };
-
-  entity.enableDrag(dragArgs);
-
-  const stopDragWatch = watch(() => [...entity.drag.position], move);
-
-  return () => {
-    entity.disableDrag();
-    stopDragWatch();
-  };
+export type EntityDragHandlers<R extends Attrib, T> = {
+  readyHandler?: (attrib: R) => T;
+  moveHandler: (attrib: R, move: number[], readyData: T) => void;
+  endHandler?: (attrib: R, readyData: T) => void;
 };
-
-export const watchEntitysOpenDrag = <
-  T,
-  K extends Attrib,
-  S extends TShape | TGroup
->(
-  getter: () => PackageBase<K, S>[],
-  handlers: DragWatchandlers<T, K>,
-  styles: {
-    hover?: GetSetPick<S> | (() => void);
-    active?: GetSetPick<S> | (() => void);
-  }
+export const openEntityDrag = <T extends Attrib, S extends ShapeType, R>(
+  entity: Entity<T, S>,
+  handler: EntityDragHandlers<T, R>
 ) => {
-  const dragWatchStopMap = new WeakMap<PackageBase<K, S>, () => void>();
-  const entryDragStop = (entry: PackageBase<K, S>) => {
-    const f = dragWatchStopMap.get(entry);
-    f && f();
-  };
-  let currentEntrys: PackageBase<K, S>[] = [];
-
-  const stopWatch = watch(
-    getter,
-    (newEntrys, oldEntrys) => {
-      const { addPort, delPort } = getChangePart(newEntrys, oldEntrys);
-      delPort.forEach(entryDragStop);
-      addPort.forEach((entry) => {
-        dragWatchStopMap.set(entry, entityOpenDrag(entry, handlers, styles));
-      });
-      currentEntrys = newEntrys;
+  entity.enableDrag({
+    readyHandler() {
+      return handler.readyHandler(entity.attrib);
     },
-    { immediate: true, flush: "pre" }
-  );
-
-  return () => {
-    stopWatch();
-    currentEntrys.forEach(entryDragStop);
-  };
+    moveHandler(move: number[], readyData: R) {
+      return handler.moveHandler(entity.attrib, move, readyData);
+    },
+    endHandler(readlyData: R) {
+      return handler.endHandler(entity.attrib, readlyData);
+    },
+  });
 };

+ 4 - 70
src/board/shared/util.ts

@@ -1,16 +1,10 @@
 import { reactive, watch } from "vue";
-import {
-  Attrib,
-  Entity,
-  EntityClass,
-  GetSetPick,
-  TGroup,
-  TLayer,
-  TShape,
-} from "../type";
+import { Attrib, GetSetPick } from "../type";
 import { inRevise, toRawType } from "./public";
+import { Shape } from "konva/lib/Shape";
+import { Group } from "konva/lib/Group";
 
-export const setShapeConfig = <T extends TShape | TGroup>(
+export const setShapeConfig = <T extends Shape | Group>(
   shape: T,
   config: GetSetPick<T>
 ) => {
@@ -64,66 +58,6 @@ export const watchAttribs = (
   );
 };
 
-export const attribsJoinEntity = <
-  T extends Attrib,
-  C extends EntityClass<T>,
-  P extends Attrib
->(
-  attribs: T[],
-  Type: C,
-  parent?: Entity<P>,
-  joinDestory = false,
-  extra?: (self: InstanceType<C>) => void
-) => {
-  const findAttrib = (id: Attrib["id"]) =>
-    attribs.find((attrib) => attrib.id === id);
-
-  const cache: { [key in Attrib["id"]]: InstanceType<C> } = reactive({});
-  const destory = (id: Attrib["id"]) => {
-    if (id in cache) {
-      cache[id].destory();
-    }
-    const shape = cache[id].getShape();
-    shape && shape.destroy();
-    delete cache[id];
-  };
-
-  const add = (id: Attrib["id"]) => {
-    const attrib = findAttrib(id);
-    if (attrib) {
-      cache[id] = new Type({
-        attrib,
-      }) as InstanceType<C>;
-      extra && extra(cache[id]);
-      cache[id].init && cache[id].init();
-      cache[id].attachBefore && cache[id].attachBefore();
-      parent && cache[id].setParent(parent);
-      cache[id].attachAfter && cache[id].attachAfter();
-    }
-  };
-
-  const stopWatchAttribs = watchAttribs(
-    attribs,
-    ({ addPort, delPort, changePort }) => {
-      delPort.forEach(destory);
-      addPort.forEach(add);
-      changePort.forEach((id) => {
-        cache[id].setAttrib(findAttrib(id));
-      });
-    }
-  );
-
-  return {
-    entitys: cache,
-    destory: () => {
-      stopWatchAttribs();
-      if (joinDestory) {
-        attribs.forEach((attrib) => destory(attrib.id));
-      }
-    },
-  };
-};
-
 export const deptComputed = <T extends Record<string, any>>(
   getter: () => T
 ) => {

+ 0 - 57
src/board/store.ts

@@ -1,57 +0,0 @@
-import { reactive, watch } from "vue";
-import { EntityClass, TLayer, Attrib } from "./type";
-import { attribsJoinEntity, getChangePart } from "./shared/util";
-
-export const setStoreData = <T extends string, R extends Attrib>(
-  data: { [key in T]: R[] },
-  newData: { [key in T]?: R[] }
-) => {
-  const { delPort } = getChangePart(Object.keys(newData), Object.keys(data));
-  for (const key in delPort) {
-    data[key] = [];
-  }
-  // 可优化
-  for (const key in newData) {
-    data[key] = newData[key];
-  }
-};
-
-export const parse = <T extends string, R extends Attrib>(
-  layer: TLayer,
-  types: { [key in T]: EntityClass<R> },
-  dataRaw: { [key in T]?: R[] } = {}
-) => {
-  let data = dataRaw as { [key in T]: R[] };
-  for (const key in types) {
-    if (!(key in data)) {
-      data[key] = [];
-    }
-  }
-  data = reactive(data) as { [key in T]: R[] };
-
-  const destory = watch(
-    () => Object.entries(data),
-    (newData, _, onCleanup) => {
-      newData.map(([key, items]) => {
-        console.log("重建" + key);
-        const join = attribsJoinEntity(
-          items as any,
-          types[key],
-          undefined,
-          true,
-          (group) => {
-            setTimeout(() => layer.add(group.getShape()));
-          }
-        );
-
-        onCleanup(join.destory);
-      });
-    },
-    { immediate: true }
-  );
-
-  return {
-    data,
-    destory,
-  };
-};

+ 2 - 41
src/board/type.d.ts

@@ -1,25 +1,15 @@
 import konva from "konva";
-import { injectDrag } from "../../shared/shape-drag";
 import { Shape } from "konva/lib/Shape";
 import { Group } from "konva/lib/Group";
 import { Layer } from "konva/lib/Layer";
 import { Stage } from "konva/lib/Stage";
 
-export type TArrow = InstanceType<typeof konva.Arrow>;
-export type TLabel = InstanceType<typeof konva.Label>;
-export type TText = InstanceType<typeof konva.Text>;
-export type TGroup = InstanceType<typeof konva.Group>;
-export type TLine = InstanceType<typeof konva.Line>;
-export type TShape = InstanceType<typeof konva.Shape>;
-export type TLayer = InstanceType<typeof konva.Layer>;
-export type TCircle = InstanceType<typeof konva.Circle>;
-
 type ShapeType = Group | Layer | Stage | Shape;
 
 interface GetSet<Type, This> {
   (a: Type): This;
 }
-export type GetSetPick<T extends TShape | TGroup> = {
+export type GetSetPick<T extends Shape | Group> = {
   [key in keyof T]?: T[key] extends GetSet<infer V, T> ? V : never;
 };
 
@@ -34,33 +24,4 @@ export type Attrib = {
   id: string;
 };
 
-export type EntityClassProps<T extends Attrib> = {
-  attrib: T;
-};
-export type EntityClass<T extends Attrib> = new (
-  props: EntityClassProps
-) => Entity<T>;
-
-export type Entity<T extends Attrib> = {
-  init?: () => void;
-  attrib: T;
-  children: Entity<Attrib>[];
-  parent: Entity<Attrib>;
-  name: string;
-  setAttrib: (attrib: T) => void;
-  destory: () => void;
-  setParent: (parent: Entity<Attrib>) => void;
-  attachAfter?: () => void;
-  attachBefore?: () => void;
-  getShape: () => TShape | TGroup;
-};
-
-export type DragEntity<T extends Attrib> = Entity<T> & {
-  drag: DragResult;
-};
-
-export type DragEntityClass<T extends Attrib> = new (
-  props: EntityClassProps<T>
-) => DragEntity<T>;
-
-export type GetShape = <T extends TShape | TGroup>(style: GetSetPick<T>) => T;
+export type GetShape = <T extends Shape | Group>(style: GetSetPick<T>) => T;

+ 3 - 5
src/components/query-board/index.vue

@@ -8,7 +8,7 @@
 
 <script setup lang="ts">
 import { ref, watch } from "vue";
-import { register } from "../../board/register";
+import { register } from "../../board/";
 import { EditWholeLine } from "../../board/packages";
 import storeData from "./storeData.json";
 
@@ -18,14 +18,12 @@ withDefaults(defineProps<{ width?: number; height?: number; pixelRation?: number
   pixelRation: 1,
 });
 
-console.log(storeData);
-
 const containerRef = ref<HTMLDivElement>();
 const initBoard = register({ rooms: EditWholeLine });
 watch(containerRef, (container, _, onClanup) => {
   if (container) {
-    const board = initBoard(container, storeData);
-    window.board = board;
+    const board = initBoard(container, storeData, false);
+    console.log(board.getData());
     onClanup(() => board.destory);
   }
 });

+ 6 - 3
vite.config.ts

@@ -1,7 +1,10 @@
-import { defineConfig } from 'vite'
-import vue from '@vitejs/plugin-vue'
+import { defineConfig } from "vite";
+import vue from "@vitejs/plugin-vue";
 
 // https://vitejs.dev/config/
 export default defineConfig({
   plugins: [vue()],
-})
+  server: {
+    port: 9005,
+  },
+});