Bladeren bron

修改bug

bill 2 jaren geleden
bovenliggende
commit
acee82beb8

File diff suppressed because it is too large
+ 1 - 1
server/test/a0k4xu045_202305311600080410/attach/sceneStore


+ 64 - 37
src/graphic/Renderer/Draw.js

@@ -149,8 +149,7 @@ export const help = {
     return (
       Math.round(
         (mathUtil.getDistance(p1, p2) * coordinate.res * 100) / coordinate.ratio
-      )
-      / 100
+      ) / 100
     );
   },
   getPerpendicularPoint(p1, p2, p3, d) {
@@ -232,12 +231,11 @@ export const help = {
       VectorStyle.PointDrawLine,
       VectorStyle.SingleDashedLine,
       VectorStyle.SingleSolidLine,
-    ]
+    ];
     if (typeof line === "function" && !funStyle.includes(style)) {
-      style = VectorStyle.SingleSolidLine
+      style = VectorStyle.SingleSolidLine;
     }
 
-
     switch (style) {
       case VectorStyle.PointDrawLine:
       case VectorStyle.SingleDashedLine:
@@ -253,8 +251,8 @@ export const help = {
           ]);
         }
 
-        if (typeof line === 'function') {
-          line()
+        if (typeof line === "function") {
+          line();
         } else {
           ctx.moveTo(line[0].x, line[0].y);
           ctx.lineTo(line[1].x, line[1].y);
@@ -426,9 +424,9 @@ export default class Draw {
     const center = coordinate.getScreenXY(vector.center);
     this.context.save();
     if (vector.scale) {
-      this.context.translate(center.x, center.y)
-      this.context.scale(vector.scale, vector.scale)
-      this.context.translate(-center.x, -center.y)
+      this.context.translate(center.x, center.y);
+      this.context.scale(vector.scale, vector.scale);
+      this.context.translate(-center.x, -center.y);
     }
     this.context.drawImage(
       img,
@@ -489,13 +487,13 @@ export default class Draw {
       };
 
       ctx.save();
-      help.setStyle(ctx, styles)
+      help.setStyle(ctx, styles);
       vector.midDivide.leftMidDivide && draw(vector.midDivide.leftMidDivide);
       vector.midDivide.rightMidDivide && draw(vector.midDivide.rightMidDivide);
 
       ctx.restore();
     }
-    console.log(styles, label, vector)
+    console.log(styles, label, vector);
 
     if (import.meta.env.DEV && !isTemp) {
       const startReal = isTemp
@@ -511,9 +509,12 @@ export default class Draw {
     }
 
     this.drawRoadEdge(vector, isTemp);
-    vector.leftLanes && vector.leftLanes.forEach((g) => this.drawLan(g, !!label));
-    vector.rightLanes && vector.rightLanes.forEach((g) => this.drawLan(g, !!label));
-    vector.singleLanes && vector.singleLanes.forEach((g) => this.drawLan(g, !!label));
+    vector.leftLanes &&
+      vector.leftLanes.forEach((g) => this.drawLan(g, !!label));
+    vector.rightLanes &&
+      vector.rightLanes.forEach((g) => this.drawLan(g, !!label));
+    vector.singleLanes &&
+      vector.singleLanes.forEach((g) => this.drawLan(g, !!label));
   }
 
   drawLan(lan, focus) {
@@ -523,9 +524,9 @@ export default class Draw {
     ctx.save();
     ctx.beginPath();
     help.setVectorStyle(ctx, null, "Lane");
-    console.log(focus)
+    console.log(focus);
     if (focus) {
-      ctx.strokeStyle = 'rgba(255, 143, 40, 1)'
+      ctx.strokeStyle = "rgba(255, 143, 40, 1)";
     }
     ctx.lineWidth *= Settings.lineWidth;
     ctx.setLineDash(Style.Lane.dash);
@@ -690,13 +691,12 @@ export default class Draw {
         vector.midDivide.leftMidDivideCurves,
         // vector.midDivide.rightMidDivideCurves,
       ]);
-      ctx.setLineDash([8 * coordinate.ratio, 8 * coordinate.ratio])
-      ctx.lineWidth *= Settings.lineWidth
+      ctx.setLineDash([8 * coordinate.ratio, 8 * coordinate.ratio]);
+      ctx.lineWidth *= Settings.lineWidth;
       for (let coves of midCovesArray) {
         help.drawCoves(ctx, coves);
       }
 
-
       // midCovesArray = help.transformCoves([
       //   vector.curves,
       // ]);
@@ -704,7 +704,6 @@ export default class Draw {
       // for (let coves of midCovesArray) {
       //   help.drawCoves(ctx, coves);
       // }
-
     }
     ctx.restore();
 
@@ -780,9 +779,14 @@ export default class Draw {
     select && help.setStyle(ctx, style);
     // ctx.lineWidth *= Settings.lineWidth;
 
-    help.drawStyleLine(this.context, () => {
-      help.drawCoves(ctx, coves);
-    }, vector.style, vector.weight);
+    help.drawStyleLine(
+      this.context,
+      () => {
+        help.drawCoves(ctx, coves);
+      },
+      vector.style,
+      vector.weight
+    );
 
     // help.drawCoves(ctx, coves);
     ctx.restore();
@@ -1015,6 +1019,15 @@ export default class Draw {
         ...style,
         ...stylea,
       };
+    } else if (vector.category === VectorCategory.Point.FixPoint) {
+      const text = dataService.getText(vector?.linkedTextId);
+      if (text) {
+        style = {
+          ...style,
+          fillStyle: text.color,
+          strokeStyle: text.color,
+        };
+      }
     }
 
     if (vector.color) {
@@ -1040,6 +1053,7 @@ export default class Draw {
       ctx.fill();
       ctx.restore();
     };
+
     if (Settings.selectBasePointId === vector.vectorId) {
       style = {
         ...style,
@@ -1130,7 +1144,6 @@ export default class Draw {
     vector.displayPoint &&
       this.drawPoint({ ...vector.center, color: vector.color }, true);
 
-
     // vector.getBound(this.context).forEach(this.drawPoint.bind(this))
   }
 
@@ -1149,9 +1162,13 @@ export default class Draw {
     this.context.scale(width / svgWidth, height / svgHidth);
     const [style, label] = help.getVectorStyle(vector);
     this.context.lineWidth = style.lineWidth / (width / svgWidth);
-    this.context.fillStyle = 'rgba(0,0,0,0)'
-    this.context.strokeStyle = 'rgba(0,0,0,0)'
-    SVGIcons[vector.type].draw(this.context, style.fillStyle || 'rgba(0,0,0,0)', style.strokeStyle || 'rgba(0,0,0,0)');
+    this.context.fillStyle = "rgba(0,0,0,0)";
+    this.context.strokeStyle = "rgba(0,0,0,0)";
+    SVGIcons[vector.type].draw(
+      this.context,
+      style.fillStyle || "rgba(0,0,0,0)",
+      style.strokeStyle || "rgba(0,0,0,0)"
+    );
     this.context.restore();
 
     if (label) {
@@ -1162,15 +1179,20 @@ export default class Draw {
       this.context.lineTo(points[2].x, points[2].y);
       this.context.lineTo(points[3].x, points[3].y);
       this.context.strokeStyle = style.strokeStyle;
-      this.context.fillStyle = 'rgba(255, 153, 0, 0.30)';
+      this.context.fillStyle = "rgba(255, 153, 0, 0.30)";
       this.context.lineWidth = 2 * coordinate.ratio;
       this.context.setLineDash([6 * coordinate.ratio, 2 * coordinate.ratio]);
       this.context.closePath();
       this.context.stroke();
-      this.context.fill()
+      this.context.fill();
       this.context.restore();
       vector.points.forEach((point) =>
-        this.drawPoint({ ...point, fillColor: '#fff', color: style.strokeStyle, radius: 5 })
+        this.drawPoint({
+          ...point,
+          fillColor: "#fff",
+          color: style.strokeStyle,
+          radius: 5,
+        })
       );
     }
   }
@@ -1245,15 +1267,20 @@ export default class Draw {
     ctx.save();
     help.setVectorStyle(ctx, vector);
 
-    help.drawStyleLine(this.context, () => {
-      help.transformCoves([vector.curves]).forEach((coves) => {
-        help.drawCoves(ctx, coves);
-      });
-    }, vector.style, vector.weight);
+    help.drawStyleLine(
+      this.context,
+      () => {
+        help.transformCoves([vector.curves]).forEach((coves) => {
+          help.drawCoves(ctx, coves);
+        });
+      },
+      vector.style,
+      vector.weight
+    );
     ctx.restore();
 
     // if (import.meta.env.DEV) {
-      vector.points.forEach(this.drawPoint.bind(this));
+    vector.points.forEach(this.drawPoint.bind(this));
     // }
   }
 

+ 59 - 57
src/views/graphic/geos/arrow.vue

@@ -3,50 +3,54 @@
     <template v-slot="{ data }">
       <template v-if="data.key === 'color'">
         <Color v-model:color="color">
-          <span class="color" :style="{backgroundColor: color}"></span>
+          <span class="color" :style="{ backgroundColor: color }"></span>
         </Color>
       </template>
     </template>
   </GeoTeleport>
-  <GeoTeleport :menus="typeMenus" v-if="typeMenus" class="type-geo" :active="typeMenus.find(menu => menu.key === type)" />
+  <GeoTeleport
+    :menus="typeMenus"
+    v-if="typeMenus"
+    class="type-geo"
+    :active="typeMenus.find((menu) => menu.key === type)"
+  />
 </template>
 
 <script setup lang="ts">
 import GeoTeleport from "@/views/graphic/geos/geo-teleport.vue";
-import {drawRef, FocusVector, uiType, UIType, useChange} from '@/hook/useGraphic'
-import {computed, ref, UnwrapRef, watch, watchEffect} from "vue";
-import {dataService} from "@/graphic/Service/DataService";
-import GeoActions from "@/graphic/enum/GeoActions"
-import {debounce} from "@/utils";
-import Color from '@/components/color/index.vue'
+
+import { drawRef, FocusVector, uiType, UIType, useChange } from "@/hook/useGraphic";
+import { computed, ref, UnwrapRef, watch, watchEffect } from "vue";
+import { dataService } from "@/graphic/Service/DataService";
+import GeoActions from "@/graphic/enum/GeoActions";
+import { debounce } from "@/utils";
+import Color from "@/components/color/index.vue";
 import VectorCategory from "@/graphic/enum/VectorCategory";
 
-const props = defineProps<{geo: FocusVector}>()
-const vector = computed(() => dataService.getLine(props.geo.vectorId))
-const color = ref("#000000")
-const type = ref(props.geo.category || "SingleArrowLine")
+const props = defineProps<{ geo: FocusVector }>();
+const vector = computed(() => dataService.getLine(props.geo.vectorId));
+const color = ref("#000000");
+const type = ref(props.geo.category || "SingleArrowLine");
 useChange(() => {
-  color.value = vector.value.color
-  type.value = vector.value.category
-})
-
+  color.value = vector.value.color;
+  type.value = vector.value.category;
+});
 
 const syncVector = ([color, type]) => {
-  vector.value.setColor(color)
-  vector.value.setCategory(type)
-  drawRef.value.renderer.autoRedraw()
-  drawRef.value.history.save()
-}
+  vector.value.setColor(color);
+  vector.value.setCategory(type);
+  drawRef.value.renderer.autoRedraw();
+  drawRef.value.history.save();
+};
 
-watch(() => [color.value, type.value], debounce(syncVector, 500))
+watch(() => [color.value, type.value], debounce(syncVector, 500));
 
-
-const typeMenus = ref<UnwrapRef<typeof menus>>()
+const typeMenus = ref<UnwrapRef<typeof menus>>();
 const menus = ref([
   {
-    key: 'color',
-    icon: 'del',
-    text: "颜色"
+    key: "color",
+    icon: "del",
+    text: "颜色",
   },
   {
     key: "type",
@@ -55,47 +59,46 @@ const menus = ref([
     onClick: () => {
       typeMenus.value = !typeMenus.value
         ? [
-          {
-            key: 'SingleArrowLine',
-            icon: 'arrows_s',
-            text: "单向",
-            onClick: () => type.value = "SingleArrowLine"
-          },
-          {
-            key: 'DoubleArrowLine',
-            icon: 'arrows_d',
-            text: "双向",
-            onClick: () => type.value = "DoubleArrowLine"
-          },
-        ]
-      : null
-    }
+            {
+              key: "SingleArrowLine",
+              icon: "arrows_s",
+              text: "单向",
+              onClick: () => (type.value = "SingleArrowLine"),
+            },
+            {
+              key: "DoubleArrowLine",
+              icon: "arrows_d",
+              text: "双向",
+              onClick: () => (type.value = "DoubleArrowLine"),
+            },
+          ]
+        : null;
+    },
   },
   {
-    key: 'copy',
-    icon: 'copy',
+    key: "copy",
+    icon: "copy",
     text: "复制",
     onClick: () => {
-      drawRef.value.uiControl.handleGeo(GeoActions.CopyAction)
-    }
+      drawRef.value.uiControl.handleGeo(GeoActions.CopyAction);
+    },
   },
   {
-    key: 'del',
-    icon: 'del',
+    key: "del",
+    icon: "del",
     text: "删除",
     onClick: () => {
-      drawRef.value.uiControl.handleGeo(GeoActions.DeleteAction)
-    }
-  }
-])
+      drawRef.value.uiControl.handleGeo(GeoActions.DeleteAction);
+    },
+  },
+]);
 
 watchEffect(() => {
-  menus.value[1].icon = type.value === "SingleArrowLine" ? "arrows_s" : "arrows_d"
-})
+  menus.value[1].icon = type.value === "SingleArrowLine" ? "arrows_s" : "arrows_d";
+});
 if (props.geo.category === VectorCategory.Line.NormalLine) {
-  menus.value.shift()
+  menus.value.shift();
 }
-
 </script>
 
 <style scoped lang="scss">
@@ -124,7 +127,6 @@ if (props.geo.category === VectorCategory.Line.NormalLine) {
 .type-geo {
   margin-bottom: 74px;
 }
-
 </style>
 
 <style lang="scss">

+ 13 - 13
src/views/graphic/geos/index.ts

@@ -1,17 +1,16 @@
-import { VectorType } from '@/hook/useGraphic'
-import Arrow from './arrow.vue'
-import Text from './text.vue'
-import Circle from './circle.vue'
-import magnifier from './magnifier.vue'
-import Del from './del.vue'
-import RoadEdge from './roadEdge.vue'
-import Road from './road.vue'
-import NormalLine from './normalLine.vue'
+import { VectorType } from "@/hook/useGraphic";
+import Arrow from "./arrow.vue";
+import Text from "./text.vue";
+import Circle from "./circle.vue";
+import magnifier from "./magnifier.vue";
+import Del from "./del.vue";
+import RoadEdge from "./roadEdge.vue";
+import Road from "./road.vue";
+import NormalLine from "./normalLine.vue";
 import VectorCategory from "@/graphic/enum/VectorCategory";
 import DelAndCopu from "@/views/graphic/geos/delAndCopu.vue";
 
-
-export const GlobalComp = Del
+export const GlobalComp = Del;
 
 export default {
   [VectorType.SVG]: DelAndCopu,
@@ -25,6 +24,7 @@ export default {
   [VectorCategory.Line.NormalLine]: NormalLine,
   [VectorType.CurveLine]: NormalLine,
   [VectorType.Text]: Text,
+  [VectorCategory.Point.FixPoint]: Text,
   [VectorType.Circle]: Circle,
-  [VectorType.Magnifier]: magnifier
-}
+  [VectorType.Magnifier]: magnifier,
+};

+ 49 - 46
src/views/graphic/geos/road.vue

@@ -1,87 +1,90 @@
 <template>
   <div class="layout">
     <GraphicAction class="full-action">
-      <ui-icon type="lock" ctrl @click="clickHandlerFactory(VectorEvents.UnLock)()"/>
+      <ui-icon type="lock" ctrl @click="clickHandlerFactory(VectorEvents.UnLock)()" />
     </GraphicAction>
-    <GeoTeleport :menus="menus" class="geo-teleport-use"  />
+    <GeoTeleport :menus="menus" class="geo-teleport-use" />
   </div>
 </template>
 
 <script setup lang="ts">
 import GeoTeleport from "@/views/graphic/geos/geo-teleport.vue";
 import UiIcon from "@/components/base/components/icon/index.vue";
-import {drawRef, FocusVector, VectorType} from '@/hook/useGraphic'
-import {computed, ref, watchEffect} from "vue";
-import {dataService} from "@/graphic/Service/DataService";
-import GeoActions from "@/graphic/enum/GeoActions"
+import { drawRef, FocusVector, VectorType } from "@/hook/useGraphic";
+import { computed, ref, watchEffect } from "vue";
+import { dataService } from "@/graphic/Service/DataService";
+import GeoActions from "@/graphic/enum/GeoActions";
 import GraphicAction from "@/components/button-pane/index.vue";
 import VectorEvents from "@/graphic/enum/VectorEvents";
 
-const props = defineProps<{geo: FocusVector}>()
-const vector = computed(() => dataService.getRoad(props.geo.vectorId))
+const props = defineProps<{ geo: FocusVector }>();
+const vector = computed(() => dataService.getRoad(props.geo.vectorId));
 const clickHandlerFactory = (key) => {
   return () => {
-    drawRef.value.uiControl.updateVectorForSelectUI(key)
-    console.log(vector)
-  }
-}
-
+    drawRef.value.uiControl.updateVectorForSelectUI(key);
+    console.log(vector);
+  };
+};
 
-const appendMenus = props.geo.type === VectorType.CurveRoad
-  ? [
-    {
-      key: VectorEvents.AddCrossPoint,
-      icon: "control_a",
-      text: "加控制点",
-      onClick: clickHandlerFactory(VectorEvents.AddCrossPoint)
-    },
-    {
-      key: VectorEvents.MinusCrossPoint,
-      icon: "control_d",
-      text: "减控制点" ,
-      onClick: clickHandlerFactory(VectorEvents.MinusCrossPoint)
-    },
-  ]
-  : []
+const appendMenus =
+  props.geo.type === VectorType.CurveRoad
+    ? [
+        {
+          key: VectorEvents.AddCrossPoint,
+          icon: "control_a",
+          text: "加控制点",
+          onClick: clickHandlerFactory(VectorEvents.AddCrossPoint),
+        },
+        {
+          key: VectorEvents.MinusCrossPoint,
+          icon: "control_d",
+          text: "减控制点",
+          onClick: clickHandlerFactory(VectorEvents.MinusCrossPoint),
+        },
+      ]
+    : [];
 const menus = ref([
   {
     key: VectorEvents.AddLane,
     icon: "lane_a",
-    text: "加车道" ,
-    onClick: clickHandlerFactory(VectorEvents.AddLane)
+    text: "加车道",
+    onClick: clickHandlerFactory(VectorEvents.AddLane),
   },
   {
     key: VectorEvents.DelLane,
     icon: "lane_d",
     text: "减车道",
-    onClick: clickHandlerFactory(VectorEvents.DelLane)
+    onClick: clickHandlerFactory(VectorEvents.DelLane),
   },
   ...appendMenus,
   {
-    key: 'copy',
-    icon: 'copy',
+    key: "copy",
+    icon: "copy",
     text: "复制",
     onClick: () => {
-      drawRef.value.uiControl.handleGeo(GeoActions.CopyAction)
-    }
+      drawRef.value.uiControl.handleGeo(GeoActions.CopyAction);
+    },
   },
   {
-    key: 'del',
-    icon: 'del',
+    key: "del",
+    icon: "del",
     text: "删除",
     onClick: () => {
-      drawRef.value.uiControl.handleGeo(GeoActions.DeleteAction)
-    }
-  }
-])
+      drawRef.value.uiControl.handleGeo(GeoActions.DeleteAction);
+    },
+  },
+]);
 
-console.log(vector.value)
+console.log(vector.value);
 watchEffect(() => {
   if (vector.value) {
-    menus.value[1].disabled = vector.value?.leftLanes.length + vector.value?.rightLanes.length + vector.value?.singleLanes.length === 0
+    menus.value[1].disabled =
+      vector.value?.leftLanes.length +
+        vector.value?.rightLanes.length +
+        vector.value?.singleLanes.length ===
+      0;
   }
-})
-
+});
 </script>
 
 <style scoped lang="scss">

+ 64 - 60
src/views/graphic/geos/text.vue

@@ -3,17 +3,17 @@
     <template v-slot="{ data }">
       <template v-if="data.key === 'color'">
         <Color v-model:color="color">
-          <span class="color" :style="{backgroundColor: color}"></span>
+          <span class="color" :style="{ backgroundColor: color }"></span>
         </Color>
       </template>
       <template v-if="data.key === 'fontSize'">
         <ui-input
-            type="select"
-            :options="sizeOption"
-            class="geo-input"
-            dire="top"
-            floatingClass="select-floating"
-            v-model="size"
+          type="select"
+          :options="sizeOption"
+          class="geo-input"
+          dire="top"
+          floatingClass="select-floating"
+          v-model="size"
         />
         <span class="font-size">{{ size }}</span>
       </template>
@@ -23,12 +23,12 @@
   <div class="text-model" v-if="updateText">
     <div class="text-input">
       <ui-input
-          ref="inputTextRef"
-          v-model="text"
-          width="100%"
-          :maxlength="20"
-          height="64px"
-          @blur="updateText = false"
+        ref="inputTextRef"
+        v-model="text"
+        width="100%"
+        :maxlength="20"
+        height="64px"
+        @blur="updateText = false"
       />
     </div>
   </div>
@@ -38,76 +38,80 @@
 import GeoTeleport from "@/views/graphic/geos/geo-teleport.vue";
 import UiInput from "@/components/base/components/input/index.vue";
 import UiIcon from "@/components/base/components/icon/index.vue";
-import {FocusVector, drawRef, useChange} from '@/hook/useGraphic'
-import {computed, ref, watch, watchEffect} from "vue";
-import {dataService} from "@/graphic/Service/DataService";
-import {debounce} from '@/utils'
+import { FocusVector, drawRef, useChange } from "@/hook/useGraphic";
+import { computed, ref, watch, watchEffect } from "vue";
+import { dataService } from "@/graphic/Service/DataService";
+import { debounce } from "@/utils";
 import GeoActions from "@/graphic/enum/GeoActions";
 import Color from "@/components/color/index.vue";
-
-const props = defineProps<{geo: FocusVector}>()
-const inputTextRef = ref()
-const updateText = ref(false)
-const vector = computed(() => dataService.getText(props.geo.vectorId))
-const text = ref("")
-const color = ref("#000000")
-const size = ref(18)
+import VectorCategory from "@/graphic/enum/VectorCategory";
+
+const props = defineProps<{ geo: FocusVector }>();
+const inputTextRef = ref();
+const updateText = ref(false);
+const vector = computed(() => {
+  let vectorId = props.geo.vectorId;
+  if (props.geo.category === VectorCategory.Point.FixPoint) {
+    vectorId = dataService.getPoint(props.geo.vectorId)?.linkedTextId;
+  }
+  return dataService.getText(vectorId);
+});
+const text = ref("");
+const color = ref("#000000");
+const size = ref(18);
 
 const syncVector = ([text, size, color]) => {
-  console.log(text, size, color)
-  vector.value.setValue(text)
-  vector.value.setColor(color)
-  vector.value.setFontSize(size)
-  drawRef.value.renderer.autoRedraw()
-  drawRef.value.history.save()
-}
+  console.log(text, size, color);
+  vector.value.setValue(text);
+  vector.value.setColor(color);
+  vector.value.setFontSize(size);
+  drawRef.value.renderer.autoRedraw();
+  drawRef.value.history.save();
+};
 
 watchEffect(() => {
   if (inputTextRef.value) {
-    inputTextRef.value.vmRef.input.focus()
+    inputTextRef.value.vmRef.input.focus();
   }
-})
+});
 
 useChange(() => {
-  color.value = vector.value.color
-  size.value = vector.value.fontSize
-  text.value = vector.value.value
-})
-watch(
-  () => [text.value, size.value, color.value],
-  debounce(syncVector, 500)
-)
+  console.log(vector.value);
+  color.value = vector.value.color;
+  size.value = vector.value.fontSize;
+  text.value = vector.value.value;
+});
+watch(() => [text.value, size.value, color.value], debounce(syncVector, 500));
 
 const sizeOption = [];
 for (let i = 10; i < 30; i++) {
-  sizeOption.push({label: i, value: i});
+  sizeOption.push({ label: i, value: i });
 }
 const menus = [
   {
-    key: 'color',
-    icon: 'del',
-    text: "颜色"
+    key: "color",
+    icon: "del",
+    text: "颜色",
   },
   {
-    key: 'fontSize',
-    text: "文字大小"
+    key: "fontSize",
+    text: "文字大小",
   },
   {
-    key: 'text',
-    icon: 'edit',
+    key: "text",
+    icon: "edit",
     text: "修改文字",
-    onClick: () => updateText.value = true
+    onClick: () => (updateText.value = true),
   },
   {
-    key: 'del',
-    icon: 'del',
+    key: "del",
+    icon: "del",
     text: "删除",
     onClick: () => {
-      drawRef.value.uiControl.handleGeo(GeoActions.DeleteAction)
-    }
-  }
-]
-
+      drawRef.value.uiControl.handleGeo(GeoActions.DeleteAction);
+    },
+  },
+];
 </script>
 
 <style scoped lang="scss">
@@ -145,8 +149,8 @@ const menus = [
   top: 0;
   right: 0;
   bottom: 0;
-  background-color: rgba(0,0,0,.8);
-  z-index: 4
+  background-color: rgba(0, 0, 0, 0.8);
+  z-index: 4;
 }
 
 .text-input {

+ 59 - 44
src/views/graphic/index.vue

@@ -1,19 +1,17 @@
 <template>
-  <MainPanel
-      :menus="store.menus as any"
-      :active-menu-key="store.activeMenuKey.value">
+  <MainPanel :menus="store.menus as any" :active-menu-key="store.activeMenuKey.value">
     <template v-slot:header>
-      <Header  />
+      <Header />
     </template>
     <Container />
     <ChildMenus
-        v-if="store.child.value && store.activeMenuKey.value === UITypeExtend.template"
-        :menus="store.child.value as any"
-        @quit="store.child.value = null"
+      v-if="store.child.value && store.activeMenuKey.value === UITypeExtend.template"
+      :menus="store.child.value as any"
+      @quit="store.child.value = null"
     />
     <ImageLabel
-        v-if="store.activeMenuKey.value === UITypeExtend.image"
-        @quit="uiType.change(null)"
+      v-if="store.activeMenuKey.value === UITypeExtend.image"
+      @quit="uiType.change(null)"
     />
 
     <GraphicAction class="full-action" v-if="!graphicState.continuedMode">
@@ -24,59 +22,76 @@
       />
     </GraphicAction>
     <Confirm v-if="graphicState.continuedMode" />
-    <Component :is="geoComponent as any" v-else-if="geoComponent" :geo="currentVector"/>
+    <Component
+      :is="geoComponent as any"
+      v-else-if="geoComponent"
+      :geo="currentVector"
+      :key="currentVector.vectorId"
+    />
   </MainPanel>
 </template>
 
 <script lang="ts" setup>
-import MainPanel from '@/components/main-panel/index.vue'
+import MainPanel from "@/components/main-panel/index.vue";
 import ChildMenus from "@/views/graphic/childMenus.vue";
-import Header from './header.vue'
-import Container from './container.vue'
-import GraphicAction from '@/components/button-pane/index.vue'
+import Header from "./header.vue";
+import Container from "./container.vue";
+import GraphicAction from "@/components/button-pane/index.vue";
 import UiIcon from "@/components/base/components/icon/index.vue";
-import Confirm from './confirm.vue'
+import Confirm from "./confirm.vue";
 import ImageLabel from "./imageLabel.vue";
-import {router} from '@/router'
-import {computed, watchEffect} from "vue";
-import {customMap} from '@/hook'
-import {focusMenuRaw, generateMixMenus, mainMenusRaw, photoMenusRaw, Mode, UITypeExtend} from './menus'
-import {currentVector, drawRef, graphicState, uiType} from "@/hook/useGraphic";
-import geos, {GlobalComp} from "./geos/index";
+import { router } from "@/router";
+
+import { computed, watchEffect } from "vue";
+import { customMap } from "@/hook";
+import {
+  focusMenuRaw,
+  generateMixMenus,
+  mainMenusRaw,
+  photoMenusRaw,
+  Mode,
+  UITypeExtend,
+} from "./menus";
+import { currentVector, drawRef, graphicState, uiType } from "@/hook/useGraphic";
+import geos, { GlobalComp } from "./geos/index";
 
 const menusRaws = computed(() => {
-  const mode = Number(router.currentRoute.value.params.mode) as Mode
-  return mode === Mode.Photo ? photoMenusRaw : mainMenusRaw
-})
-const store = computed(() => generateMixMenus(
-  "extend",
-  (mainMenuRaw) => ({
-    ...mainMenuRaw,
-    title: mainMenuRaw.text,
-    name: mainMenuRaw.key,
-    isRoute: false,
-    // icon: 'menu',
-    bottom:  mainMenuRaw.key === UITypeExtend.setup
-  }),
-  menusRaws.value
-))
+  const mode = Number(router.currentRoute.value.params.mode) as Mode;
+  return mode === Mode.Photo ? photoMenusRaw : mainMenusRaw;
+});
+const store = computed(() =>
+  generateMixMenus(
+    "extend",
+    (mainMenuRaw) => ({
+      ...mainMenuRaw,
+      title: mainMenuRaw.text,
+      name: mainMenuRaw.key,
+      isRoute: false,
+      // icon: 'menu',
+      bottom: mainMenuRaw.key === UITypeExtend.setup,
+    }),
+    menusRaws.value
+  )
+);
 
 watchEffect(() => {
   if (graphicState.value.continuedMode) {
-    customMap.sysView = 'full'
+    customMap.sysView = "full";
   } else {
-    customMap.sysView = 'auto'
+    customMap.sysView = "auto";
   }
-})
+});
 
-const focusMenus = computed(() => focusMenuRaw[currentVector.value?.type])
+const focusMenus = computed(() => focusMenuRaw[currentVector.value?.type]);
 const geoComponent = computed(() => {
   if (currentVector.value) {
-    console.log(currentVector.value)
-    return geos[currentVector.value?.type] || geos[currentVector.value?.category] || GlobalComp
+    console.log(currentVector.value);
+    return (
+      geos[currentVector.value?.category] || geos[currentVector.value?.type] || GlobalComp
+    );
   }
-})
-const isFull = computed(() => customMap.sysView === 'full' )
+});
+const isFull = computed(() => customMap.sysView === "full");
 </script>
 
 <style lang="scss" scoped>

+ 96 - 82
src/views/photos/index.vue

@@ -1,42 +1,57 @@
 <template>
   <MainPanel>
     <template v-slot:header>
-      <Header :count="selects.length" :title="`全部照片(${photos.length})`" type="return" :on-back="() => router.back()">
-        <ui-button type="primary" @click="selectMode = !selectMode" width="96px" v-if="sortPhotos.length">
-          {{ selectMode ? '取消' : '选择' }}
+      <Header
+        :count="selects.length"
+        :title="`全部照片(${photos.length})`"
+        type="return"
+        :on-back="() => router.back()"
+      >
+        <ui-button
+          type="primary"
+          @click="selectMode = !selectMode"
+          width="96px"
+          v-if="sortPhotos.length"
+        >
+          {{ selectMode ? "取消" : "选择" }}
         </ui-button>
       </Header>
     </template>
 
     <Photos
       undata-msg="无照片。请返回场景拍照以获取照片"
-      :getURL="data => data.urlRaw || data.url"
+      :getURL="(data) => data.urlRaw || data.url"
       v-model:active="active"
       v-model:selects="selects"
       :select-mode="selectMode"
       :data="sortPhotos"
     />
-<!--    @click="router.push(writeRouteName.scene)"-->
+    <!--    @click="router.push(writeRouteName.scene)"-->
     <ButtonPane class="back fun-ctrl" v-if="!selectMode">
       <ui-icon type="photo" class="icon" />
       <ui-input
-          type="select"
-          :options="photoOptions"
-          dire="top"
-          class="select"
-          v-model="photoType"
+        type="select"
+        :options="photoOptions"
+        dire="top"
+        class="select"
+        v-model="photoType"
       />
     </ButtonPane>
 
-    <ActionMenus class="select-menus" :menus="selectMenus" dire="row" v-if="selects.length" />
+    <ActionMenus
+      class="select-menus"
+      :menus="selectMenus"
+      dire="row"
+      v-if="selects.length"
+    />
   </MainPanel>
 
   <FillSlide
-      :data="sortPhotos"
-      v-model:active="active"
-      @quit="active = null"
-      v-if="active"
-      :getURL="data => data.urlRaw || data.url"
+    :data="sortPhotos"
+    v-model:active="active"
+    @quit="active = null"
+    v-if="active"
+    :getURL="(data) => data.urlRaw || data.url"
   >
     <template v-slot:foot>
       <ActionMenus class="menus" :menus="menus" dire="row" />
@@ -45,146 +60,146 @@
 </template>
 
 <script setup lang="ts">
-import MainPanel from '@/components/main-panel/index.vue'
-import FillSlide from '@/components/fill-slide/index.vue'
-import Header from '@/components/photos/header.vue'
-import {PhotoRaw, photos} from '@/store/photos'
+import MainPanel from "@/components/main-panel/index.vue";
+import FillSlide from "@/components/fill-slide/index.vue";
+import Header from "@/components/photos/header.vue";
+import { PhotoRaw, photos } from "@/store/photos";
 import UiIcon from "@/components/base/components/icon/index.vue";
-import {router, writeRouteName} from '@/router'
+import { router, writeRouteName } from "@/router";
 import ButtonPane from "@/components/button-pane/index.vue";
-import {computed, onDeactivated, ref, watchEffect} from "vue";
-import {Mode} from '@/views/graphic/menus'
+import { computed, onDeactivated, ref, watchEffect } from "vue";
+import { Mode } from "@/views/graphic/menus";
 import UiButton from "@/components/base/components/button/index.vue";
-import Photos from '@/components/photos'
+import Photos from "@/components/photos/index.vue";
 import ActionMenus from "@/components/group-button/index.vue";
-import {useConfirm} from "@/hook";
+import { useConfirm } from "@/hook";
 import UiInput from "@/components/base/components/input/index.vue";
-import {api} from "@/store/sync";
-import {getId} from "@/utils";
+import { api } from "@/store/sync";
+import { getId } from "@/utils";
 
-const sortPhotos = computed(() => [...photos.value].reverse())
-const active = ref<PhotoRaw>()
-const selectMode = ref(false)
-const selects = ref<PhotoRaw[]>([])
+const sortPhotos = computed(() => [...photos.value].reverse());
+const active = ref<PhotoRaw>();
+const selectMode = ref(false);
+const selects = ref<PhotoRaw[]>([]);
 const menus = [
   {
     key: "road",
     text: "现场绘图",
     icon: "draw_s",
-    onClick: () => gotoDraw(Mode.Road)
+    onClick: () => gotoDraw(Mode.Road),
   },
   {
     key: "accident",
     icon: "label",
     text: "照片标注",
-    onClick: () => gotoDraw(Mode.Photo)
+    onClick: () => gotoDraw(Mode.Photo),
   },
   {
     key: "del",
     icon: "del",
     text: "删除",
-    onClick: () => delPhoto()
-  }
-]
+    onClick: () => delPhoto(),
+  },
+];
 
 const selectMenus = [
   {
     key: "del",
     icon: "del",
     text: "删除",
-    onClick: () => delSelects()
+    onClick: () => delSelects(),
   },
-]
+];
 
-const photoType = ref<string>()
+const photoType = ref<string>();
 const photoOptions = [
-  {value: "photograph", label: "相机拍照"},
-  {value: "selectPhotoAlbum", label: "相册选择"},
-  {value: "scene", label: "场景截图"},
-]
+  { value: "photograph", label: "相机拍照" },
+  { value: "selectPhotoAlbum", label: "相册选择" },
+  { value: "scene", label: "场景截图" },
+];
 
 watchEffect(() => {
   if (photoType.value) {
     if (photoType.value === "scene") {
-      router.push(writeRouteName.scene)
+      router.push(writeRouteName.scene);
     } else {
-      api[photoType.value]()
-        .then(url => {
-          photos.value.push({
-            id: getId(),
-            url,
-            urlRaw: url,
-            time: new Date().getTime(),
-            meterPerPixel: null,
-            measures: [],
-            baseLines: [],
-            fixPoints: [],
-            basePoints: []
-          })
-        })
+      api[photoType.value]().then((url) => {
+        photos.value.push({
+          id: getId(),
+          url,
+          urlRaw: url,
+          time: new Date().getTime(),
+          meterPerPixel: null,
+          measures: [],
+          baseLines: [],
+          fixPoints: [],
+          basePoints: [],
+        });
+      });
     }
-    photoType.value = null
+    photoType.value = null;
   }
-})
+});
 
 watchEffect(() => {
   if (!selectMode.value) {
-    selects.value = []
+    selects.value = [];
   }
-})
+});
 
 const delPhotoRaw = (photo = active.value) => {
-  const index = photos.value.indexOf(photo)
-  const reset = active.value ? photos.value.indexOf(active.value) : -1
+  const index = photos.value.indexOf(photo);
+  const reset = active.value ? photos.value.indexOf(active.value) : -1;
   if (~index) {
-    photos.value.splice(index, 1)
+    photos.value.splice(index, 1);
   }
   if (~reset) {
     if (reset >= photos.value.length) {
       if (photos.value.length) {
-        active.value = photos.value[photos.value.length - 1]
+        active.value = photos.value[photos.value.length - 1];
       } else {
-        active.value = null
+        active.value = null;
       }
     } else {
-      active.value = photos.value[reset]
+      active.value = photos.value[reset];
     }
   }
-}
+};
 const delPhoto = async (photo = active.value) => {
   if (await useConfirm(`确定要删除此数据?`)) {
-    delPhotoRaw(photo)
+    delPhotoRaw(photo);
   }
-}
+};
 const delSelects = async () => {
   if (await useConfirm(`确定要删除这${selects.value.length}项数据?`)) {
     while (selects.value.length) {
-      delPhotoRaw(selects.value[0])
-      selects.value.shift()
+      delPhotoRaw(selects.value[0]);
+      selects.value.shift();
     }
     if (!sortPhotos.value.length) {
-      selectMode.value = false
+      selectMode.value = false;
     }
   }
-}
+};
 
 const gotoDraw = (mode: Mode) => {
   router.push({
     name: writeRouteName.graphic,
-    params: {mode, id: active.value.id, action: 'add'}
-  })
-}
+    params: { mode, id: active.value.id, action: "add" },
+  });
+};
 
 onDeactivated(() => {
-  active.value = null
-})
+  active.value = null;
+  selectMode.value = false;
+});
 </script>
 
 <style scoped lang="scss">
 .fun-ctrl {
   color: #fff;
   font-size: 20px;
-  transition: color .3s ease;
+  transition: color 0.3s ease;
 
   .icon {
     position: absolute;
@@ -217,5 +232,4 @@ onDeactivated(() => {
   transform: translateX(-50%);
   bottom: var(--boundMargin);
 }
-
 </style>

+ 76 - 73
src/views/roads/index.vue

@@ -1,21 +1,26 @@
 <template>
   <MainPanel>
     <template v-slot:header>
-      <Header :count="selects.length" :title="`现场图管理(${sortPhotos.length})`" type="return_l" :on-back="() => api.closePage()">
+      <Header
+        :count="selects.length"
+        :title="`现场图管理(${sortPhotos.length})`"
+        type="return_l"
+        :on-back="() => api.closePage()"
+      >
         <ui-button
-            :type="selectMode ? 'primary' : 'normal'"
-            @click="selectMode = !selectMode"
-            width="96px"
-            style="margin-right: 16px"
-            v-if="sortPhotos.length"
+          :type="selectMode ? 'primary' : 'normal'"
+          @click="selectMode = !selectMode"
+          width="96px"
+          style="margin-right: 16px"
+          v-if="sortPhotos.length"
         >
-          {{ selectMode ? '取消' : '选择' }}
+          {{ selectMode ? "取消" : "选择" }}
         </ui-button>
         <ui-button
-            v-if="!selectMode"
-            type="primary"
-            @click="router.push({name: writeRouteName.photos})"
-            width="96px"
+          v-if="!selectMode"
+          type="primary"
+          @click="router.push({ name: writeRouteName.photos })"
+          width="96px"
         >
           新增
         </ui-button>
@@ -23,28 +28,32 @@
     </template>
 
     <Photos
-        undata-msg="无现场图。请点击右上角按钮绘制现场图。"
-        v-model:active="active"
-        v-model:selects="selects"
-        :select-mode="selectMode"
-        :data="sortPhotos"
-        :getURL="data => data?.table?.url || data.url"
+      undata-msg="无现场图。请点击右上角按钮绘制现场图。"
+      v-model:active="active"
+      v-model:selects="selects"
+      :select-mode="selectMode"
+      :data="sortPhotos"
+      :getURL="(data) => data?.table?.url || data.url"
     >
-      <template v-slot="{data}">
-        <p>{{ data.title || '默认标题' }}</p>
+      <template v-slot="{ data }">
+        <p>{{ data.title || "默认标题" }}</p>
       </template>
     </Photos>
 
-
-    <ActionMenus class="select-menus" :menus="selectMenus" dire="row" v-if="selects.length" />
+    <ActionMenus
+      class="select-menus"
+      :menus="selectMenus"
+      dire="row"
+      v-if="selects.length"
+    />
   </MainPanel>
 
   <FillSlide
-      :getURL="data => data?.table?.url || data.url"
-      :data="sortPhotos"
-      v-model:active="active"
-      @quit="active = null"
-      v-if="active"
+    :getURL="(data) => data?.table?.url || data.url"
+    :data="sortPhotos"
+    v-model:active="active"
+    @quit="active = null"
+    v-if="active"
   >
     <template v-slot:foot>
       <ActionMenus class="menus" :menus="menus" dire="row" />
@@ -53,106 +62,102 @@
 </template>
 
 <script setup lang="ts">
-import MainPanel from '@/components/main-panel/index.vue'
-import FillSlide from '@/components/fill-slide/index.vue'
-import {roadPhotos, RoadPhoto} from '@/store/roadPhotos'
+import MainPanel from "@/components/main-panel/index.vue";
+import FillSlide from "@/components/fill-slide/index.vue";
+import { roadPhotos, RoadPhoto } from "@/store/roadPhotos";
 import ActionMenus from "@/components/group-button/index.vue";
-import {router, writeRouteName} from '@/router'
-import {computed, onDeactivated, ref, watchEffect} from "vue";
-import {Mode} from '@/views/graphic/menus'
+import { router, writeRouteName } from "@/router";
+import { computed, onDeactivated, ref, watchEffect } from "vue";
+import { Mode } from "@/views/graphic/menus";
 import UiButton from "@/components/base/components/button/index.vue";
 import Header from "@/components/photos/header.vue";
 import Photos from "@/components/photos/index.vue";
 import ButtonPane from "@/components/button-pane/index.vue";
 import UiIcon from "@/components/base/components/icon/index.vue";
-import {useConfirm} from "@/hook";
-import {api} from "@/store/sync";
-import {photos} from "@/store/photos";
-
-
-const sortPhotos = computed(() => [...roadPhotos.value].reverse())
-const active = ref<RoadPhoto>()
-const selectMode = ref(false)
-const selects = ref<RoadPhoto[]>([])
+import { useConfirm } from "@/hook";
+import { api } from "@/store/sync";
+import { photos } from "@/store/photos";
+
+const sortPhotos = computed(() => [...roadPhotos.value].reverse());
+const active = ref<RoadPhoto>();
+const selectMode = ref(false);
+const selects = ref<RoadPhoto[]>([]);
 const menus = [
   {
     key: "road",
     icon: "edit",
     text: "修改",
-    onClick: () => gotoDraw()
+    onClick: () => gotoDraw(),
   },
   {
     key: "del",
     icon: "del",
     text: "删除",
-    onClick: () => delPhoto()
-  }
-]
+    onClick: () => delPhoto(),
+  },
+];
 
 const selectMenus = [
   {
     key: "del",
     icon: "del",
     text: "删除",
-    onClick: () => delSelects()
+    onClick: () => delSelects(),
   },
-]
+];
 
 watchEffect(() => {
   if (!selectMode.value) {
-    selects.value = []
+    selects.value = [];
   }
-})
+});
 
 const delPhotoRaw = (roadPhoto = active.value) => {
-  const index = roadPhotos.value.indexOf(roadPhoto)
-  const reset = active.value ? roadPhotos.value.indexOf(active.value) : -1
+  const index = roadPhotos.value.indexOf(roadPhoto);
+  const reset = active.value ? roadPhotos.value.indexOf(active.value) : -1;
   if (~index) {
-    roadPhotos.value.splice(index, 1)
+    roadPhotos.value.splice(index, 1);
   }
   if (~reset) {
     if (reset >= roadPhotos.value.length) {
       if (roadPhotos.value.length) {
-        active.value = roadPhotos.value[roadPhotos.value.length - 1]
+        active.value = roadPhotos.value[roadPhotos.value.length - 1];
       } else {
-        active.value = null
+        active.value = null;
       }
     } else {
-      active.value = roadPhotos.value[reset]
+      active.value = roadPhotos.value[reset];
     }
   }
-}
+};
 
 const delPhoto = async (photo = active.value) => {
   if (await useConfirm(`确定要删除此数据?`)) {
-    delPhotoRaw(photo)
+    delPhotoRaw(photo);
   }
-
-}
+};
 const delSelects = async () => {
   if (await useConfirm(`确定要删除这${selects.value.length}项数据?`)) {
     while (selects.value.length) {
-      delPhotoRaw(selects.value[0])
-      selects.value.shift()
+      delPhotoRaw(selects.value[0]);
+      selects.value.shift();
     }
     if (!sortPhotos.value.length) {
-      selectMode.value = false
+      selectMode.value = false;
     }
   }
-}
-
+};
 
 const gotoDraw = () => {
   router.push({
     name: writeRouteName.graphic,
-    params: {mode: Mode.Road, id: active.value.id, action: 'update'}
-  })
-}
+    params: { mode: Mode.Road, id: active.value.id, action: "update" },
+  });
+};
 
 onDeactivated(() => {
-  active.value = null
-})
-
+  active.value = null;
+});
 </script>
 
 <style scoped lang="scss">
@@ -170,7 +175,7 @@ onDeactivated(() => {
 .fun-ctrl {
   color: #fff;
   font-size: 20px;
-  transition: color .3s ease;
+  transition: color 0.3s ease;
 
   .icon {
     position: absolute;
@@ -184,11 +189,9 @@ onDeactivated(() => {
   bottom: var(--boundMargin);
 }
 
-
 .select-menus {
   left: 50%;
   transform: translateX(-50%);
   bottom: var(--boundMargin);
 }
-
 </style>

+ 9 - 10
src/views/scene/mode.vue

@@ -8,10 +8,10 @@
 </template>
 
 <script lang="ts" setup>
-import GroupButton from '@/components/group-button/index.vue'
-import {Mode} from "@/sdk";
-import {computed, ref, watch, watchEffect} from "vue";
-import {customMap, disabledMap} from "@/hook/custom/index";
+import GroupButton from "@/components/group-button/index.vue";
+import { Mode } from "@/sdk";
+import { computed, ref, watch, watchEffect } from "vue";
+import { customMap, disabledMap } from "@/hook/custom/index";
 
 const tabs = [
   {
@@ -28,14 +28,14 @@ const tabs = [
 
 const activeKey = ref(tabs[0].mode);
 const menus = computed(() =>
-  tabs.map(tab => ({
+  tabs.map((tab) => ({
     icon: tab.mode === activeKey.value ? tab.activeIcon : tab.icon,
     key: tab.mode,
-    onClick: () => activeKey.value = tab.mode
+    onClick: () => (activeKey.value = tab.mode),
   }))
-)
+);
 
-watch(activeKey, () => customMap.mode = activeKey.value)
+watch(activeKey, () => (customMap.mode = activeKey.value));
 </script>
 
 <style lang="scss" scoped>
@@ -55,5 +55,4 @@ watch(activeKey, () => customMap.mode = activeKey.value)
   }
 }
 </style>
-<script setup lang="ts">
-</script>
+<script setup lang="ts"></script>