فهرست منبع

Merge branch 'master' of http://192.168.0.115:3000/bill/traffic-laser

xzw 2 سال پیش
والد
کامیت
07ce390c01
65فایلهای تغییر یافته به همراه306 افزوده شده و 99 حذف شده
  1. 2 0
      server/mock.ts
  2. 1 0
      server/test/SS-t-P1d6CwREny2/attach/floor_0_vision.txt
  3. 1 1
      server/test/SS-t-P1d6CwREny2/attach/sceneStore
  4. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685518090910611.jpg
  5. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685520124861337.jpg
  6. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685520158221265.jpg
  7. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685520752118646.jpg
  8. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/168552108627021.jpg
  9. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685521100958725.jpg
  10. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685521116786961.jpg
  11. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685521130035543.jpg
  12. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685521148222535.jpg
  13. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685521159254605.jpg
  14. BIN
      server/test/SS-t-P1d6CwREny2/attach/upload/1685521184172334.jpg
  15. 1 0
      server/test/SS-t-P1d6CwREny2/attach/vision.json
  16. 1 1
      server/test/a0k4xu045_202305311600080410/attach/sceneStore
  17. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685522025979634.jpg
  18. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685526052186380.jpg
  19. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685526111353443.jpg
  20. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685526113065592.jpg
  21. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685526134152409.jpg
  22. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685526152705630.jpg
  23. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685581812129495.jpg
  24. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685581883868282.jpg
  25. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685581888778190.jpg
  26. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685582198712327.jpg
  27. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685586211010602.jpg
  28. BIN
      server/test/a0k4xu045_202305311600080410/attach/upload/1685587254252480.jpg
  29. 11 2
      src/components/group-button/index.vue
  30. 3 0
      src/graphic/Coordinate.js
  31. 26 2
      src/graphic/Geometry/Img.js
  32. 3 2
      src/graphic/Geometry/Magnifier.js
  33. 9 0
      src/graphic/Geometry/Text.js
  34. 5 1
      src/graphic/History/HistoryUtil.js
  35. 27 7
      src/graphic/Layer.js
  36. 2 0
      src/graphic/ListenLayer.js
  37. 35 16
      src/graphic/Load.js
  38. 1 1
      src/graphic/Renderer/Draw.js
  39. 29 1
      src/graphic/Service/ImageService.js
  40. BIN
      src/graphic/a0k4xu045_202305301709276070.zip
  41. 3 0
      src/hook/custom/preset.ts
  42. 1 1
      src/hook/useGraphic.ts
  43. 1 1
      src/hook/useParams.ts
  44. 3 1
      src/sdk/types/sdk.ts
  45. 1 1
      src/store/photos.ts
  46. 6 5
      src/store/sync.ts
  47. 1 1
      src/views/accidents/index.vue
  48. 2 1
      src/views/graphic/geos/magnifier.vue
  49. 1 1
      src/views/photos/index.vue
  50. 12 9
      src/views/scene/container.vue
  51. 16 7
      src/views/scene/covers/basePoint.vue
  52. 11 5
      src/views/scene/covers/cover.vue
  53. 15 5
      src/views/scene/covers/fixPoint.vue
  54. BIN
      src/views/scene/covers/icon/point_f_s.png
  55. BIN
      src/views/scene/covers/icon/point_s_n.png
  56. BIN
      src/views/scene/covers/icon/point_s_s.png
  57. BIN
      src/views/scene/covers/icon/pointf_n.png
  58. 3 1
      src/views/scene/covers/measure.vue
  59. 17 5
      src/views/scene/covers/measures.vue
  60. BIN
      src/views/scene/covers/point1.png
  61. 28 4
      src/views/scene/menus/menus.ts
  62. 14 3
      src/views/scene/menus/pane.vue
  63. 6 5
      src/views/scene/mode.vue
  64. 7 8
      src/views/scene/photo.vue
  65. 1 1
      src/views/sys/mode-tab/index.vue

+ 2 - 0
server/mock.ts

@@ -39,8 +39,10 @@ export async function createServer(port: number) {
     const file = (req as any).files.file
     const relUrl = `/attach/upload/${file.name}`
     const absUrl = path.resolve(staticDir, `./${req.params.sceneCode}/${relUrl}`)
+    console.log("上传图片完成路径为", relUrl)
     file.mv(absUrl, err => {
       if (err) {
+        res.status(404)
         res.json({code: 1, msg: 'ok'})
       } else {
         res.json({code: 0, msg: 'ok', data: relUrl})

+ 1 - 0
server/test/SS-t-P1d6CwREny2/attach/floor_0_vision.txt

@@ -0,0 +1 @@
+{}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
server/test/SS-t-P1d6CwREny2/attach/sceneStore


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685518090910611.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685520124861337.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685520158221265.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685520752118646.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/168552108627021.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685521100958725.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685521116786961.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685521130035543.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685521148222535.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685521159254605.jpg


BIN
server/test/SS-t-P1d6CwREny2/attach/upload/1685521184172334.jpg


+ 1 - 0
server/test/SS-t-P1d6CwREny2/attach/vision.json

@@ -0,0 +1 @@
+{}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
server/test/a0k4xu045_202305311600080410/attach/sceneStore


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685522025979634.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685526052186380.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685526111353443.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685526113065592.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685526134152409.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685526152705630.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685581812129495.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685581883868282.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685581888778190.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685582198712327.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685586211010602.jpg


BIN
server/test/a0k4xu045_202305311600080410/attach/upload/1685587254252480.jpg


+ 11 - 2
src/components/group-button/index.vue

@@ -5,7 +5,7 @@
       :key="menu.key"
       class="menu"
       :style="menuStyle"
-      :class="{ active: activeKey === menu.key, dire, disabled: menu.disabled }"
+      :class="{ active: activeKey === menu.key, dire, disabled: disabledMap[menu.key] }"
       @click="menu.onClick && menu.onClick(menu)"
     >
       <template v-if="$slots.default">
@@ -26,7 +26,7 @@ type Menu =  {
   key: any,
   text?: string,
   icon?: string,
-  disabled?: boolean
+  disabled?: boolean | (() => boolean)
   onClick?: (menu: Menu) => void
 }
 
@@ -35,6 +35,15 @@ const props = withDefaults(
   {dire: 'row', size: 64}
 )
 
+const disabledMap = computed(() => {
+  const map = {}
+  for (let menu of props.menus) {
+    map[menu.key] = !menu.disabled ? false :
+      typeof menu.disabled === "boolean" ? menu.disabled : menu.disabled()
+  }
+  return map
+})
+
 const menuStyle = computed(() => {
   const offset = props.size / 4;
   return props.dire === 'row'

+ 3 - 0
src/graphic/Coordinate.js

@@ -1,7 +1,9 @@
+import Constant from "./Constant";
 import { dataService } from "./Service/DataService";
 
 const defaultZoom = 100;
 const defaultRes = 1;
+const minAdsorbPix = 20;
 
 export default class Coordinate {
   constructor() {
@@ -91,6 +93,7 @@ export default class Coordinate {
       this.height = canvas.height;
     }
     this.setCenter(canvas);
+    Constant.minAdsorbPix = minAdsorbPix * this.ratio;
     console.log(
       "updateForCanvas" +
         canvas.offsetWidth +

+ 26 - 2
src/graphic/Geometry/Img.js

@@ -1,6 +1,7 @@
 import { mathUtil } from "../Util/MathUtil.js";
 import VectorType from "../enum/VectorType.js";
 import Geometry from "./Geometry";
+import {api} from '@/store/sync.ts'
 
 export default class Img extends Geometry {
   constructor(src, vectorId) {
@@ -10,6 +11,7 @@ export default class Img extends Geometry {
     this.display = true;
     this.center = null;
     this.imageData = null;
+    this.bounding = null;
     this.geoType = VectorType.Img;
     this.setId(vectorId);
     this.setSrc(src);
@@ -24,9 +26,9 @@ export default class Img extends Geometry {
   }
 
   setImageData() {
-    return new Promise((resolve, reject) => {
+    return new Promise(async (resolve, reject) => {
       this.imageData = new Image();
-      this.imageData.src = this.src;
+      this.imageData.src = await api.getFile(this.src);
       this.imageData.onload = function () {
         resolve();
       };
@@ -35,4 +37,26 @@ export default class Img extends Geometry {
       };
     });
   }
+
+  setBounding() {
+    const width = this.imageData.width;
+    const height = this.imageData.height;
+    this.bounding = [];
+    this.bounding[0] = {
+      x: this.center.x - width / 2,
+      y: this.center.y + height / 2,
+    };
+    this.bounding[1] = {
+      x: this.center.x + width / 2,
+      y: this.center.y + height / 2,
+    };
+    this.bounding[2] = {
+      x: this.center.x + width / 2,
+      y: this.center.y - height / 2,
+    };
+    this.bounding[3] = {
+      x: this.center.x - width / 2,
+      y: this.center.y - height / 2,
+    };
+  }
 }

+ 3 - 2
src/graphic/Geometry/Magnifier.js

@@ -4,6 +4,7 @@ import { coordinate } from "../Coordinate.js";
 import { mathUtil } from "../Util/MathUtil.js";
 import VectorType from "../enum/VectorType.js";
 import Geometry from "./Geometry";
+import {api} from '@/store/sync.ts'
 
 const distance = 500;
 export default class Magnifier extends Geometry {
@@ -141,10 +142,10 @@ export default class Magnifier extends Geometry {
   }
 
   setImageData() {
-    return new Promise((resolve, reject) => {
+    return new Promise(async (resolve, reject) => {
       if (this.photoUrl) {
         this.photoImage = new Image();
-        this.photoImage.src = this.photoUrl;
+        this.photoImage.src = await api.getFile(this.photoUrl);
         this.photoImage.onload = function () {
           resolve();
         };

+ 9 - 0
src/graphic/Geometry/Text.js

@@ -11,12 +11,21 @@ export default class Text extends Geometry {
     super();
     this.center = center;
     this.value = "固定点";
+    this.angle = 0;
     this.color = Style.Text.fillStyle;
     this.fontSize = Style.Text.fontSize;
     this.geoType = VectorType.Text;
     this.setId(vectorId);
   }
 
+  getAngle() {
+    return this.angle;
+  }
+
+  setAngle(angle) {
+    this.angle = angle;
+  }
+
   setValue(value) {
     this.value = value;
   }

+ 5 - 1
src/graphic/History/HistoryUtil.js

@@ -75,7 +75,8 @@ export default class HistoryUtil {
   isDifferentForTexts(text1, text2) {
     if (
       mathUtil.equalPoint(text1.center, text2.center) &&
-      text1.value == text2.value
+      text1.value == text2.value &&
+      text1.angle == text2.angle
     ) {
       return false;
     } else {
@@ -317,6 +318,7 @@ export default class HistoryUtil {
     textInfo.vectorId = text1.vectorId;
     textInfo.value = text2.value;
     textInfo.center = JSON.parse(JSON.stringify(text2.center));
+    textInfo.angle = text2.angle;
     this.setTextInfo(textInfo);
   }
 
@@ -552,6 +554,7 @@ export default class HistoryUtil {
     const data = {};
     data.id = text.vectorId;
     data.type = text.geoType;
+    data.angle = text.angle;
     data.center = {};
     mathUtil.clonePoint(data.center, text.center);
     data.value = text.value;
@@ -771,6 +774,7 @@ export default class HistoryUtil {
     text.vectorId = textInfo.vectorId;
     text.center = JSON.parse(JSON.stringify(textInfo.center));
     text.value = textInfo.value;
+    text.angle = textInfo.angle;
   }
 
   setMagnifierInfo(magnifierInfo) {

+ 27 - 7
src/graphic/Layer.js

@@ -38,6 +38,7 @@ import { curveRoadService } from "./Service/CurveRoadService";
 import VectorCategory from "./enum/VectorCategory";
 import Settings from "./Settings";
 import { uiService } from "./Service/UIService";
+import { imageService } from "./Service/ImageService";
 
 const minDragDis = 10;
 const minZoom = 20;
@@ -285,13 +286,21 @@ export default class Layer {
         break;
       case LayerEvents.PanBackGround:
         stateService.clearItems();
-        coordinate.center.x =
+        let center = {};
+        center.x =
           coordinate.center.x - (dx * coordinate.defaultZoom) / coordinate.zoom;
-        coordinate.center.y =
+        center.y =
           coordinate.center.y + (dy * coordinate.defaultZoom) / coordinate.zoom;
-
-        dataService.setGridForPan();
-        needAutoRedraw = true;
+        let tempCenter = {};
+        mathUtil.clonePoint(tempCenter, coordinate.center);
+        mathUtil.clonePoint(coordinate.center, center);
+        let inScreen = imageService.backgroundImgVertexsInScreenXY();
+        if (!inScreen) {
+          dataService.setGridForPan();
+          needAutoRedraw = true;
+        } else {
+          mathUtil.clonePoint(coordinate.center, tempCenter);
+        }
         break;
       case LayerEvents.AddRoad:
         needAutoRedraw = true;
@@ -981,9 +990,20 @@ export default class Layer {
     if (zoom < minZoom || zoom > maxZoom) {
       return;
     }
+
+    let tempCenter = {};
+    mathUtil.clonePoint(tempCenter, coordinate.center);
+    let tempZoom = coordinate.zoom;
     coordinate.updateZoom(position, zoom);
-    dataService.setGridForZoom();
-    this.renderer.autoRedraw();
+
+    let inScreen = imageService.backgroundImgVertexsInScreenXY();
+    if (!inScreen) {
+      dataService.setGridForZoom();
+      this.renderer.autoRedraw();
+    } else {
+      mathUtil.clonePoint(coordinate.center, tempCenter);
+      coordinate.zoom = tempZoom;
+    }
   }
 
   //测试用

+ 2 - 0
src/graphic/ListenLayer.js

@@ -1308,6 +1308,8 @@ export default class ListenLayer {
         VectorType.Circle,
         this.modifyPoint.index
       );
+    } else {
+      stateService.clearSelectItem();
     }
 
     let newSelectItem = stateService.getSelectItem();

+ 35 - 16
src/graphic/Load.js

@@ -21,7 +21,7 @@ export default class Load {
     this.layer.initLocation();
     if (dataLocal) {
       if (dataLocal.backgroundImg) {
-        let bgImg = imageService.create(
+        let bgImg = imageService.createBackgroundImg(
           dataLocal.backgroundImg.src,
           dataLocal.backgroundImg.vectorId
         );
@@ -31,6 +31,7 @@ export default class Load {
         try {
           if (dataLocal.backgroundImg.src) {
             await bgImg.setImageData();
+            bgImg.setBounding();
           }
         } catch (e) {}
       }
@@ -61,15 +62,6 @@ export default class Load {
           } catch (e) {}
         }
       }
-      if (dataLocal.texts) {
-        for (let key in dataLocal.texts) {
-          let text = textService.create(dataLocal.texts[key].center, key);
-          text.setValue(dataLocal.texts[key].value);
-          text.setFontSize(dataLocal.texts[key].fontSize);
-          text.setColor(dataLocal.texts[key].color);
-          text.setDisplay(dataLocal.texts[key].display);
-        }
-      }
       if (dataLocal.points) {
         for (let key in dataLocal.points) {
           let point = pointService.create(dataLocal.points[key], key);
@@ -80,6 +72,7 @@ export default class Load {
           point.setDisplay(dataLocal.points[key].display);
         }
       }
+
       if (dataLocal.lines) {
         for (let key in dataLocal.lines) {
           let line = lineService.createByPointId(
@@ -100,6 +93,16 @@ export default class Load {
           }
         }
       }
+      if (dataLocal.texts) {
+        for (let key in dataLocal.texts) {
+          let text = textService.create(dataLocal.texts[key].center, key);
+          text.setValue(dataLocal.texts[key].value);
+          text.setFontSize(dataLocal.texts[key].fontSize);
+          text.setColor(dataLocal.texts[key].color);
+          text.setDisplay(dataLocal.texts[key].display);
+          text.setAngle(dataLocal.texts[key].angle || 0);
+        }
+      }
       if (dataLocal.hasOwnProperty("currentId")) {
         dataService.setCurrentId(dataLocal.currentId);
       }
@@ -108,11 +111,15 @@ export default class Load {
       }
     } else if (data3d) {
       if (data3d.backImage) {
-        let bgImg = imageService.create(data3d.backImage, data3d.vectorId);
+        let bgImg = imageService.createBackgroundImg(
+          data3d.backImage,
+          data3d.vectorId
+        );
         bgImg.setCenter(coordinate.center);
         try {
           if (bgImg.src) {
             await bgImg.setImageData();
+            bgImg.setBounding();
           }
         } catch (e) {}
         if (data3d.meterPerPixel) {
@@ -120,7 +127,7 @@ export default class Load {
         }
         const width = bgImg.imageData.width;
         const height = bgImg.imageData.height;
-
+        let angle = 0;
         if (data3d.baseLines) {
           for (let i = 0; i < data3d.baseLines.length; ++i) {
             //理论上基准线只能有一条
@@ -130,6 +137,15 @@ export default class Load {
               VectorCategory.Line.BaseLine
             );
             Settings.baseLineId = baseLine.vectorId;
+
+            //文字要和基准线的方向一致
+            if (typeof baseLine.a != "undefined") {
+              angle = Math.atan(baseLine.a);
+            } else if (baseLine.hasOwnProperty("x")) {
+              angle = Math.PI / 2;
+            } else {
+              angle = 0;
+            }
           }
         }
         if (data3d.measures) {
@@ -154,10 +170,13 @@ export default class Load {
         }
         if (data3d.fixPoints) {
           for (let i = 0; i < data3d.fixPoints.length; ++i) {
-            let point = pointService.create(
-              this.getXY(width, height, data3d.fixPoints[i])
-            );
-            point.setCategory(VectorCategory.Point.FixPoint);
+            // let point = pointService.create(
+            //   this.getXY(width, height, data3d.fixPoints[i].pos)
+            // );
+            // point.setCategory(VectorCategory.Point.FixPoint);
+            let text = textService.create(data3d.fixPoints[i].pos);
+            text.setValue(data3d.fixPoints[i].text);
+            text.setAngle(data3d.fixPoints[i].angle || 0);
           }
         }
       }

+ 1 - 1
src/graphic/Renderer/Draw.js

@@ -705,7 +705,7 @@ export default class Draw {
     this.context.font = `${
       vector.fontSize * coordinate.ratio
     }px Microsoft YaHei`;
-    this.drawTextByInfo(vector.center, vector.value, 0, false);
+    this.drawTextByInfo(vector.center, vector.value, (vector.angle || 0) *(Math.PI / 180), false);
 
     const ctx = this.context;
     const pt = coordinate.getScreenXY(vector.center);

+ 29 - 1
src/graphic/Service/ImageService.js

@@ -1,15 +1,43 @@
 import Img from "../Geometry/Img.js";
 import { dataService } from "./DataService.js";
 import { mathUtil } from "../Util/MathUtil";
+import { coordinate } from "../Coordinate.js";
 
 export default class ImageService {
   constructor() {}
 
-  create(src, vectorId) {
+  createBackgroundImg(src, vectorId) {
     let img = new Img(src, vectorId);
     dataService.addBackgroundImg(img);
     return img;
   }
+
+  //判断背景图片是否在屏幕外
+  backgroundImgVertexsInScreenXY() {
+    function isInScreen(position) {
+      if (
+        (position.x > 0 && position.x < coordinate.width) ||
+        (position.y > 0 && position.y < coordinate.height)
+      ) {
+        return true;
+      } else {
+        return false;
+      }
+    }
+
+    let bgImg = dataService.getBackgroundImg();
+    let vertexs = [];
+    vertexs[0] = coordinate.getScreenXY(bgImg.bounding[0]);
+    vertexs[1] = coordinate.getScreenXY(bgImg.bounding[1]);
+    vertexs[2] = coordinate.getScreenXY(bgImg.bounding[2]);
+    vertexs[3] = coordinate.getScreenXY(bgImg.bounding[3]);
+    let flag =
+      isInScreen(vertexs[0]) ||
+      isInScreen(vertexs[1]) ||
+      isInScreen(vertexs[2]) ||
+      isInScreen(vertexs[3]);
+    return flag; //true表示在屏幕内,false表示在屏幕外
+  }
 }
 
 const imageService = new ImageService();

BIN
src/graphic/a0k4xu045_202305301709276070.zip


+ 3 - 0
src/hook/custom/preset.ts

@@ -20,6 +20,7 @@ export enum DisabledCom {
   floors = "floors",
   lmenu = "lmenu",
   autoLeave = "autoLeave",
+  Mode = 'mode'
 }
 
 export const searchDisabledStack = stackFactory(ref(false));
@@ -39,6 +40,7 @@ export const toolDisabled = stackFactory(ref(false));
 export const floorsDisabled = stackFactory(ref(false));
 export const lmenuDisabled = stackFactory(ref(false));
 export const autoLeaveDisabled = stackFactory(ref(false));
+export const modeDisabled = stackFactory(ref(false));
 
 export const disabledMapStack = {
   [DisabledCom.Search]: searchDisabledStack,
@@ -59,6 +61,7 @@ export const disabledMapStack = {
   [DisabledCom.floors]: floorsDisabled,
   [DisabledCom.lmenu]: lmenuDisabled,
   [DisabledCom.autoLeave]: autoLeaveDisabled,
+  [DisabledCom.Mode]: modeDisabled,
 } as { [key in DisabledCom]: Stack<Ref<boolean>> };
 
 export type DisabledMapStack = typeof disabledMapStack;

+ 1 - 1
src/hook/useGraphic.ts

@@ -55,7 +55,7 @@ export const setCanvas = async (canvas: HTMLCanvasElement, data: Ref<AccidentPho
           console.log("load", data.value)
           drawRef.value.load.load(data.value.data, {
             ...data.value.sceneData,
-            backImage: await api.getFile(data.value.photoUrl)
+            backImage: data.value.photoUrl
           })
         } else {
           drawRef.value.load.clear()

+ 1 - 1
src/hook/useParams.ts

@@ -21,7 +21,7 @@ export const setParams = (p: Params) => (params = p);
 
 export const useParams = () => params;
 
-//params.m = "SS-t-P1d6CwREny2"
+// params.m = "SS-t-P1d6CwREny2"
 if (params.test) {
   params.test = true;
 } else {

+ 3 - 1
src/sdk/types/sdk.ts

@@ -69,7 +69,7 @@ export type Measure = {
     dataUrl: string;
     pose: Pose;
   };
-  bus: Emitter<{ update: Measure; highlight: boolean, firstClickMarker: void }>;
+  bus: Emitter<{ update: Measure; selected: boolean, firstClickMarker: void }>;
   getDatasets: () => Array<string>;
   getDatasetId: () => string;
   getDatasetLocations: () => Array<Pos3D>;
@@ -447,6 +447,8 @@ export type LaserSDK = {
   map: Map;
   scene: Scene;
   enterDatasetsManage: () => any;
+  enterTopView: () => any,
+  leaveTopView: () => any,
   leaveDatasetsManage: () => any;
   getPointByEntity: (id: string) => Pos3D;
   entityIncludePoint: (id: string, pos: Pos3D) => boolean;

+ 1 - 1
src/store/photos.ts

@@ -7,7 +7,7 @@ export type PhotoRaw = {
   meterPerPixel: number
   time: number,
   measures: { pos: Pos[], dis: number}[],
-  fixPoints: Array<Pos>,
+  fixPoints: Array<{ text:string, pos: Pos }>,
   basePoints: Array<Pos>
   baseLines: Array<Pos[]>
 }

+ 6 - 5
src/store/sync.ts

@@ -16,8 +16,8 @@ const global = window as any;
 
 let count = 0;
 export const api =
-  // import.meta.env.DEV && !global.android
-  true
+  import.meta.env.DEV && !global.android
+  // true
     ? // const api = import.meta.env.DEV
       {
         async setStore(data) {
@@ -47,7 +47,7 @@ export const api =
           url = url.trim();
           const paths = url.split("/")
           const notBase64BaseTypes = [
-            ".png", ".jpg", ".bin"
+            ".png", ".jpg"
           ]
           const notBase64 = notBase64BaseTypes.some(type => paths[paths.length - 1].includes(type))
           if (notBase64) {
@@ -97,7 +97,8 @@ export const api =
 
           const paths = fileUrl.split("/")
           const notBase64BaseTypes = [
-            ".png", ".jpg", ".bin"
+            // ".png", ".jpg"
+            // , ".bin"
           ]
           const notBase64 = notBase64BaseTypes.some(type => paths[paths.length - 1].includes(type))
 
@@ -105,7 +106,7 @@ export const api =
             return await new Promise<string>((resolve) => {
               const apiName = `getImageCallback${count++}`
               global[apiName] = (base64) => {
-                console.error("请求url:" + fileUrl, "返回:" + base64.substring(0, 60))
+                // console.error("请求url:" + fileUrl, "返回:" + base64.substring(0, 60))
                 resolve(URL.createObjectURL(base64ToBlob(base64)));
                 delete global[apiName]
               };

+ 1 - 1
src/views/accidents/index.vue

@@ -1,7 +1,7 @@
 <template>
   <MainPanel>
     <template v-slot:header>
-      <Header :count="selects.length" :title="`标注照片(${sortPhotos.length})`">
+      <Header :count="selects.length" :title="`标注照片(${sortPhotos.length})`">
         <ui-button
             :type="selectMode ? 'primary' : 'normal'"
             @click="selectMode = !selectMode"

+ 2 - 1
src/views/graphic/geos/magnifier.vue

@@ -51,7 +51,8 @@ const menus = [
 watch(
   () => [file.value],
   async ([blob]) => {
-    syncVector(await api.getFile(await uploadImage(blob)))
+    // console.log(blob)
+    syncVector(await uploadImage(blob))
   }
 )
 

+ 1 - 1
src/views/photos/index.vue

@@ -1,7 +1,7 @@
 <template>
   <MainPanel>
     <template v-slot:header>
-      <Header :count="selects.length" title="照片管理">
+      <Header :count="selects.length" :title="`全部照片(${photos.length})`">
         <ui-button type="primary" @click="selectMode = !selectMode" width="96px">
           {{ selectMode ? '取消' : '选择' }}
         </ui-button>

+ 12 - 9
src/views/scene/container.vue

@@ -6,7 +6,7 @@
 
 <script setup lang="ts">
 import {onMounted, ref, watchEffect} from "vue";
-import {customMap, setupLaser, useLoading, useParams} from "@/hook";
+import {customMap, disabledMap, setupLaser, useLoading, useParams} from "@/hook";
 import {store} from "@/store";
 import {currentApp} from "@/store/app";
 import {axios} from "@/dbo/";
@@ -40,14 +40,17 @@ onMounted(async () => {
   setTimeout(() => {
     watchEffect(() => {
       const doms = Array.from(sceneLayoutRef.value.querySelectorAll("#navCube, #home")) as HTMLElement[]
-      if (customMap.mode === Mode.pano) {
-        doms.forEach(dom => {
-          dom.style.display = "none"
-        })
-      } else {
-        doms.forEach(dom => {
-          dom.style.display = "block"
-        })
+      console.log("====>", disabledMap.mode)
+      if (!disabledMap.mode) {
+        if (customMap.mode === Mode.pano) {
+          doms.forEach(dom => {
+            dom.style.display = "none"
+          })
+        } else {
+          doms.forEach(dom => {
+            dom.style.display = "block"
+          })
+        }
       }
     })
     Loading.hideAll()

+ 16 - 7
src/views/scene/covers/basePoint.vue

@@ -2,26 +2,35 @@
   <Cover
       @change-pos="pos => $emit('changePos', pos)"
       :pos="pos"
-      @focus="$emit('focus')"
-      @blur="$emit('blur')"
+      @focus="active = true"
+      @blur="active = false"
   >
-    <img :src="icon" class="label" />
+    <img :src="active ? activeIcon : icon" class="label" />
   </Cover>
 
 </template>
 
 <script setup lang="ts">
 import Cover from './cover.vue'
-import icon from './point1.png'
+import icon from './icon/point_s_n.png'
+import activeIcon from './icon/point_s_s.png'
 import {Pos3D} from '@/sdk'
-import {watchEffect} from "vue";
+import {ref, watchEffect} from "vue";
 
 const props = defineProps<{ pos: Pos3D }>()
-defineEmits<{
+const active = ref(false)
+const emit = defineEmits<{
   (m: 'changePos', pos: Pos3D): void,
   (m: 'focus'): void,
-  (m: 'blur'): void
+  (m: 'blur'): void,
 }>()
+watchEffect(() => {
+  if (active.value) {
+    emit('focus')
+  } else {
+    emit('blur')
+  }
+})
 </script>
 
 <style scoped lang="scss">

+ 11 - 5
src/views/scene/covers/cover.vue

@@ -1,11 +1,12 @@
 <template>
   <div
       class="cover-layout"
-      @click.stop.prevent="clickHandler"
+      @click="clickHandler"
       @mousedown.stop.prevent="downHandler"
       @touchstart.stop.prevent="downHandler"
       :class="{ move: move }"
       :style="style"
+      ref="dom"
   >
     <slot />
   </div>
@@ -17,13 +18,16 @@ import {Pos, Pos3D} from '@/sdk'
 import {useSDK} from '@/hook'
 import { getPostionByTarget} from '@/components/base/utils'
 
-const props = defineProps<{ pos: Pos3D }>()
+const props = defineProps<{
+  pos: Pos3D
+}>()
 const emit = defineEmits<{
   (m: 'changePos', pos: Pos3D): void
   (m: 'focus'): void
   (m: 'blur'): void
 }>()
 const sdk = useSDK()
+const dom = ref<HTMLElement>()
 
 const screen = ref<Pos>(null)
 const style = computed(
@@ -95,9 +99,11 @@ const downHandler = (sev: MouseEvent | TouchEvent) => {
 const clickHandler = ev => {
   emit("focus")
 
-  const handler = () => {
-    emit("blur")
-    document.documentElement.removeEventListener("click", handler)
+  const handler = (ev: MouseEvent) => {
+    if (!dom.value.contains(ev.target as HTMLElement) && ev.target !== dom.value) {
+      emit("blur")
+      document.documentElement.removeEventListener("click", handler)
+    }
   }
   document.documentElement.addEventListener("click", handler, { passive: true })
 }

+ 15 - 5
src/views/scene/covers/fixPoint.vue

@@ -2,12 +2,12 @@
   <Cover
       @change-pos="pos => $emit('changePos', pos)"
       :pos="data.pos"
-      @focus="$emit('focus')"
-      @blur="$emit('blur')"
+      @focus="active = true"
+      @blur="active = false"
       class="fix-cover"
   >
     <div class="label">
-      <img :src="icon" />
+      <img :src="active ? activeIcon : icon" />
       <p>{{ data.text }}</p>
     </div>
   </Cover>
@@ -16,16 +16,26 @@
 
 <script setup lang="ts">
 import Cover from './cover.vue'
-import icon from './point1.png'
+import icon from './icon/pointf_n.png'
+import activeIcon from './icon/point_f_s.png'
 import {Pos3D} from '@/sdk'
 import {FixPoint} from "@/store/fixPoint";
+import {ref, watchEffect} from "vue";
 
 const props = defineProps<{ data: FixPoint }>()
-defineEmits<{
+const active = ref(false)
+const emit = defineEmits<{
   (m: 'changePos', pos: Pos3D): void,
   (m: 'focus'): void,
   (m: 'blur'): void,
 }>()
+watchEffect(() => {
+  if (active.value) {
+    emit('focus')
+  } else {
+    emit('blur')
+  }
+})
 </script>
 
 <style scoped lang="scss">

BIN
src/views/scene/covers/icon/point_f_s.png


BIN
src/views/scene/covers/icon/point_s_n.png


BIN
src/views/scene/covers/icon/point_s_s.png


BIN
src/views/scene/covers/icon/pointf_n.png


+ 3 - 1
src/views/scene/covers/measure.vue

@@ -21,7 +21,8 @@ const measure = computed(() => {
 
 watchEffect(() => {
   if (measure.value) {
-    measure.value.bus.on("highlight", (focus) => {
+    measure.value.bus.on("selected", (focus) => {
+      console.error("measure highlight")
       if (focus) {
         emit('focus')
       } else {
@@ -30,6 +31,7 @@ watchEffect(() => {
     })
 
     measure.value.bus.on("update", () => {
+      console.error("measure update", measure.value.getPoints())
       emit("changePoints", measure.value.getPoints())
     })
   }

+ 17 - 5
src/views/scene/covers/measures.vue

@@ -1,9 +1,9 @@
 <template>
   <Measure
-      v-for="measure in list"
+      v-for="measure in list.concat(baseLines)"
       :key="measure.id"
       :data="measure"
-      @change-points="points => measure.points = points"
+      @change-points="points => changePoints(measure, points)"
       @blur="() => active = active === measure ? null : active"
       @focus="() => active = measure"
   />
@@ -13,11 +13,18 @@
 
 <script setup lang="ts">
 import { list, MeasureAtom } from '@/store/measure'
+import { baseLines } from '@/store/baseLine'
 import Measure from './measure.vue'
 import {ref} from "vue";
 import ActionsPanel from "@/views/scene/covers/actions.vue";
 
 const active = ref<MeasureAtom>()
+const getStore = (item: MeasureAtom) =>
+  ~list.value.indexOf(item)
+    ? list.value
+    : ~baseLines.value.indexOf(item)
+      ? baseLines.value
+      : null
 const activeActionMenus = [
   {
     key: "delete",
@@ -25,11 +32,16 @@ const activeActionMenus = [
     color: "#FF4D4F",
     iconColor: "#fff",
     action() {
-      const index = list.value.indexOf(active.value)
-      if (~index) {
-        list.value.splice(index, 1)
+      const store = getStore(active.value)
+      if (store) {
+        store.splice(store.indexOf(active.value), 1)
       }
+      active.value = null
     }
   }
 ]
+
+const changePoints = (measure, points) => {
+  measure.points = points.map(point => ({...point}))
+}
 </script>

BIN
src/views/scene/covers/point1.png


+ 28 - 4
src/views/scene/menus/menus.ts

@@ -1,13 +1,18 @@
 import {findMenuByAttr, generateMixMenus as generateMixMenusRaw} from '@/utils/menus'
-import {ref} from "vue";
+import {computed, Ref, ref} from "vue";
+import {useSDK} from "@/hook";
+import {laserModeStack, modeDisabled} from '@/hook/custom/index'
+import {Mode} from "@/sdk";
+import {baseLines} from "@/store/baseLine";
 
 export type MenuRaw = {
   key: string,
   text: string,
   continued?: boolean
   icon?: string,
+  disabled?: boolean | (() => boolean),
   children?: MenuRaw[],
-  onClick?: () => void
+  onClick?: () => void | (() => void)
 }
 
 export enum menuEnum {
@@ -71,13 +76,32 @@ export const menus: MenuRaw[] = [
   },
   {
     icon: "standard",
-    text: "基准线/点",
+    text: "基准",
     key: "baseLineOrPoint",
+    onClick() {
+      const sdk = useSDK()
+      const doms = document.querySelectorAll("#navCube, #home") as NodeListOf<HTMLElement>;
+      laserModeStack.push(ref(Mode.cloud))
+      console.log("push")
+      modeDisabled.push(ref(true))
+      doms.forEach(dom => dom.style.display = "none");
+      // sdk.enterTopView()
+
+      console.log(modeDisabled.current.value.value)
+      return () => {
+        doms.forEach(dom => dom.style.display = "block");
+        laserModeStack.pop()
+        console.log("pop")
+        modeDisabled.pop()
+        // sdk.leaveTopView()
+      }
+    },
     children: [
       {
         icon: "line",
         text: "基准线",
-        key: menuEnum.BASE_LINE
+        key: menuEnum.BASE_LINE,
+        disabled: () => !!baseLines.value.length
       },
       {
         icon: "point",

+ 14 - 3
src/views/scene/menus/pane.vue

@@ -16,9 +16,9 @@
 
 <script lang="ts" setup>
 import ActionMenus from "@/components/group-button/index.vue";
-import {generateMixMenus, MenuRaw, menus} from './menus'
+import {generateMixMenus, MenuRaw, menus, findMenuByKey} from './menus'
 import {joinActions} from './actions'
-import {computed, onUnmounted} from "vue";
+import {computed, onUnmounted, watchEffect} from "vue";
 
 const props = withDefaults(
   defineProps<{ menus?: MenuRaw[], level?: number }>(),
@@ -27,7 +27,7 @@ const props = withDefaults(
 const emit = defineEmits<{ (e: 'back'): void }>();
 const backMenu = {
   icon: "return",
-  text: "返回",
+  text: "",
   key: "back",
   onClick: () => emit("back")
 }
@@ -40,6 +40,17 @@ const store = generateMixMenus(
   m => m,
   menusMix.value
 )
+
+watchEffect((onCleanup) => {
+  const menu = store.activeMenuKey.value && findMenuByKey(store.activeMenuKey.value)
+  if (store.child && menu?.onClick) {
+    const leaveHook = menu.onClick()
+    leaveHook && onCleanup(leaveHook)
+  } else {
+    onCleanup(() => {})
+  }
+})
+
 onUnmounted(joinActions(store.itemActiveKey));
 </script>
 <script lang="ts"> export default {name: 'scene-menus'}</script>

+ 6 - 5
src/views/scene/mode.vue

@@ -3,14 +3,15 @@
     class="scene-mode-tabs"
     :menus="menus"
     :active-key="activeKey"
+    v-if="!disabledMap.mode"
   />
 </template>
 
 <script lang="ts" setup>
 import GroupButton from '@/components/group-button/index.vue'
 import {Mode} from "@/sdk";
-import {computed, ref, watchEffect} from "vue";
-import {customMap} from "@/hook";
+import {computed, ref, watch, watchEffect} from "vue";
+import {customMap, disabledMap} from "@/hook/custom/index";
 
 const tabs = [
   {
@@ -34,9 +35,7 @@ const menus = computed(() =>
   }))
 )
 
-watchEffect(() => {
-  customMap.mode = activeKey.value
-})
+watch(activeKey, () => customMap.mode = activeKey.value)
 </script>
 
 <style lang="scss" scoped>
@@ -56,3 +55,5 @@ watchEffect(() => {
   }
 }
 </style>
+<script setup lang="ts">
+</script>

+ 7 - 8
src/views/scene/photo.vue

@@ -39,15 +39,14 @@ if (photos.value[photos.value.length - 1]?.url) {
 
 const tempPhoto = ref<string>();
 const coverRef = ref<HTMLImageElement>()
-const getCurrentScreens = (poss: Array<Pos3D>): Array<Pos> => {
+const getCurrentScreen = (pos: Pos3D): Pos => {
   const sdk = useSDK()
-  return poss
-    .map(pos => {
-      const data = sdk.scene.getScreenByPoint(pos)
-      return data.trueSide ? data.pos : null
-    })
-    .filter(pos => !!pos);
+  const data = sdk.scene.getScreenByPoint(pos)
+  return data.trueSide ? data.pos : null
 }
+const getCurrentScreens = (poss: Array<Pos3D>): Array<Pos> =>
+  poss.map(getCurrentScreen).filter(pos => !!pos);
+
 const photo = genUseLoading(async () => {
   const sdk = useSDK()
   const dom = sdk.scene.el
@@ -90,7 +89,7 @@ const photo = genUseLoading(async () => {
       baseLines: baseLines.value
         .map(data => getCurrentScreens(data.points))
         .filter(poss => poss.length),
-      fixPoints: getCurrentScreens(fixPoints.value.map(data => data.pos)),
+      fixPoints: fixPoints.value.map(data => ({ text: data.text, pos: getCurrentScreen(data.pos) })),
       basePoints: getCurrentScreens(basePoints.value.map(data => data.pos))
     })
     showCoverUrl.value = await api.getFile(url)

+ 1 - 1
src/views/sys/mode-tab/index.vue

@@ -9,7 +9,7 @@
         (customMap.full === 'map' && !disabledMap.clound),
       'full-ctrl': customMap.fullCtrl,
     }"
-    v-if="!inDisabled && tabs.length"
+    v-if="!disabledMap.mode && !inDisabled && tabs.length"
   >
     <ui-guide
       :msg="customMap.mode !== item.mode ? item.markDesc : ''"