فهرست منبع

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

jinx 1 سال پیش
والد
کامیت
c169635ffa

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


+ 162 - 0
src/components/vrange/index.vue

@@ -0,0 +1,162 @@
+<template>
+  <div class="right-range floating-range" v-if="props">
+    <span
+      class="fun-ctrl"
+      @click="emit('update:value', value - step > min ? value - step : value)"
+    >
+      -
+    </span>
+    <div class="range-content">
+      <div class="range-layout">
+        <ui-input
+          type="range"
+          v-bind="props"
+          :modelValue="value"
+          @update:modelValue="(val) => emit('update:value', val)"
+          :moveCallback="changeRange"
+          :ctrl="false"
+          :input="false"
+          width="100%"
+        />
+
+        <span
+          class="num"
+          :style="{
+            left: `${((value - min) / (max - min)) * 100}%`,
+          }"
+        >
+          {{ parseInt(value.toString()) + unit }}
+        </span>
+      </div>
+    </div>
+    <span
+      class="fun-ctrl"
+      @click="emit('update:value', value + step > min ? value + step : value)"
+    >
+      +
+    </span>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { Pos } from "@/sdk";
+const props = defineProps<{
+  max: number;
+  min: number;
+  step: number;
+  unit: string;
+  value: number;
+}>();
+
+const emit = defineEmits<{
+  (event: "update:value", data: number): void;
+}>();
+
+const changeRange = (sp: Pos, cp: Pos, info: { start: number; locusWidth: number }) =>
+  info.start + (sp.y - cp.y) / info.locusWidth;
+</script>
+
+<style lang="scss" scoped>
+.floating-range {
+  margin-left: 20px;
+  transform: translateY(-50%);
+  background: none;
+  border-radius: 16px;
+  display: flex;
+  align-items: center;
+  justify-self: center;
+
+  .fun-ctrl {
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+    margin: 0 24px;
+    font-size: 24px;
+    transform: rotate(-90deg);
+  }
+  .range-content {
+    display: flex;
+    align-items: center;
+    width: 290px;
+    height: 16px;
+    .range-layout {
+      height: 100%;
+      width: 100%;
+      position: relative;
+    }
+
+    .num {
+      position: absolute;
+      color: #fff;
+      top: 0;
+      margin-top: -32px;
+      transform: translateY(-100%) translateX(calc(-50% - 10px)) rotate(90deg);
+      background: #2e2e2e;
+      border-radius: 8px;
+      padding: 10px;
+      font-size: 20px;
+      pointer-events: none;
+      white-space: nowrap;
+
+      &::before {
+        content: "";
+        border: 8px solid transparent;
+        position: absolute;
+        right: -15px;
+        border-left-color: #2e2e2e;
+        top: 50%;
+        transform: translateY(-50%);
+      }
+    }
+  }
+}
+
+.right-range {
+  position: absolute;
+  padding: 0;
+  border-radius: 20px;
+  right: 10px;
+  top: 50%;
+  z-index: 2;
+  transform: translateX(40%) rotate(-90deg);
+
+  .range-content {
+    align-items: center;
+
+    span {
+      margin: 0 10px;
+      font-size: 20px;
+      flex: none;
+      color: #fff;
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+.floating-range .ui-input .range {
+  --height: 16px !important;
+  --colors-normal-back: rgba(255, 255, 255, 0.3);
+
+  .range-content {
+    --slideSize: calc(var(--height) + 16px) !important;
+
+    &::before {
+      border-start-end-radius: 8px;
+      border-end-end-radius: 8px;
+    }
+  }
+
+  .range-slide {
+    width: 16px;
+    height: 32px;
+    border-radius: 8px;
+  }
+  .range-locus {
+    width: calc(100% - 16px);
+  }
+}
+.opacity-range {
+  margin-left: 70px;
+}
+</style>

+ 7 - 0
src/graphic/CanvasStyle/default.js

@@ -118,6 +118,12 @@ const NormalLine = {
   strokeStyle: "#2F8FFF",
   lineWidth: 1 * coordinate.ratio,
 };
+const ZebraCrossing = {
+  strokeStyle: "#2F8FFF",
+  lineWidth: 20 * coordinate.ratio,
+  dash: [2 * coordinate.ratio, 4 * coordinate.ratio],
+};
+
 const CurveLine = {
   ...NormalLine,
 };
@@ -236,6 +242,7 @@ export default {
   LocationLineByFixPoint: MeasureLine,
   LocationLineByBasePoint: MeasureLine,
   NormalPoint,
+  ZebraCrossing,
   Measure,
   Element,
   TestPoint,

+ 6 - 0
src/graphic/CanvasStyle/focus.js

@@ -118,10 +118,16 @@ const SVG = {
   lineWidth: 2 * coordinate.ratio,
 };
 
+const ZebraCrossing = {
+  ...def.ZebraCrossing,
+  strokeStyle: "rgba(255, 143, 40, 1)",
+};
+
 export default {
   Road,
   Text,
   Point,
+  ZebraCrossing,
   SVG,
   SingleArrowLine,
   DoubleArrowLine,

+ 8 - 6
src/graphic/Renderer/Draw.js

@@ -1128,12 +1128,14 @@ export default class Draw {
         ctx.restore();
         return;
       }
-      const [stylea, attr] = help.getVectorStyle(line, line.category);
-      style = {
-        ...style,
-        ...stylea,
-        fillStyle: attr ? "#fff" : stylea.strokeStyle,
-      };
+      if (line.category !== "ZebraCrossing") {
+        const [stylea, attr] = help.getVectorStyle(line, line.category);
+        style = {
+          ...style,
+          ...stylea,
+          fillStyle: attr ? "#fff" : stylea.strokeStyle,
+        };
+      }
     } else if (vector.category === VectorCategory.Point.FixPoint) {
       const text = dataService.getText(vector?.linkedTextId);
       if (text) {

+ 17 - 25
src/views/graphic/geos/geo-teleport.vue

@@ -1,38 +1,33 @@
 <template>
   <div class="geo-teleport">
-    <ActionMenus
-        class="menus "
-        :menus="menus"
-        dire="row"
-        :activeKey="active?.key"
-    >
-      <template v-slot="{data}">
+    <ActionMenus class="menus" :menus="menus" dire="row" :activeKey="active?.key">
+      <template v-slot="{ data }">
         <div class="menu-layout" v-if="!data.onClick">
           <slot :data="data" />
         </div>
-        <ui-icon :type="data.icon" class="icon" v-else />
+        <ui-icon :type="data.icon" class="icon" v-else-if="!data.desc" />
+        <p v-else>{{ data.desc }}</p>
       </template>
     </ActionMenus>
   </div>
 </template>
 
 <script setup lang="ts">
-import ActionMenus from '@/components/group-button/index.vue'
-import {onMounted} from "vue";
+import ActionMenus from "@/components/group-button/index.vue";
+import { onMounted } from "vue";
 import UiIcon from "@/components/base/components/icon/index.vue";
 
-type Menu =  {
-  key: any,
-  text?: string,
-  icon?: string,
-  onClick?: (menu: Menu) => void
-}
+type Menu = {
+  key: any;
+  text?: string;
+  icon?: string;
+  onClick?: (menu: Menu) => void;
+};
 
-defineProps<{ menus: Menu[], active?: Menu }>()
+defineProps<{ menus: Menu[]; active?: Menu }>();
 </script>
 
 <style scoped lang="scss">
-
 .icon {
   font-size: 16px;
 }
@@ -50,27 +45,26 @@ defineProps<{ menus: Menu[], active?: Menu }>()
   position: static;
 }
 .menu {
-
   min-width: 56px;
   display: flex;
   flex-direction: column;
   cursor: pointer;
   height: 100%;
   text-align: center;
-  transition: color .3s ease;
+  transition: color 0.3s ease;
   color: #fff;
   border-radius: 4px;
 
-
   //&:hover,
   &.active {
     color: var(--colors-primary-base);
   }
 
   &.active {
-    background: rgba(255, 255, 255, 0.1);;
+    background: rgba(255, 255, 255, 0.1);
   }
 
+  p,
   .icon {
     display: flex;
     align-items: center;
@@ -82,11 +76,10 @@ defineProps<{ menus: Menu[], active?: Menu }>()
   p {
     line-height: 17px;
     font-size: 12px;
-    white-space:nowrap;
+    white-space: nowrap;
   }
 }
 
-
 .menu-layout {
   height: 22px;
   margin-bottom: 3px;
@@ -96,7 +89,6 @@ defineProps<{ menus: Menu[], active?: Menu }>()
   justify-content: center;
   //overflow-y: hidden;
 }
-
 </style>
 
 <style lang="scss">

+ 41 - 52
src/views/graphic/geos/roadEdge.vue

@@ -1,18 +1,26 @@
 <template>
   <GeoTeleport :menus="menus" class="geo-teleport-use" :active="active" />
   <GeoTeleport :menus="childMenus" v-if="childMenus" class="type-geo" />
+  {{ showChange }}
+  <VRange
+    v-if="showChange"
+    :max="100"
+    :min="10"
+    :step="1"
+    unit="mm"
+    v-model:value="(lineWidthMenu[2].desc as number)"
+  />
 </template>
 
 <script setup lang="ts">
 import GeoTeleport from "@/views/graphic/geos/geo-teleport.vue";
-import { drawRef, FocusVector, VectorType } from "@/hook/useGraphic";
-import { computed, ref, toRaw, UnwrapRef } from "vue";
+import { drawRef, FocusVector } from "@/hook/useGraphic";
+import { computed, reactive, ref, toRaw, UnwrapRef, watchEffect } from "vue";
 import { dataService } from "@/graphic/Service/DataService";
-import GeoActions from "@/graphic/enum/GeoActions";
 import { UITypeExtend } from "@/views/graphic/menus";
-import VectorEvents from "@/graphic/enum/VectorEvents";
 import VectorStyle from "@/graphic/enum/VectorStyle";
 import VectorWeight from "@/graphic/enum/VectorWeight";
+import VRange from "@/components/vrange/index.vue";
 
 const props = defineProps<{ geo: FocusVector }>();
 const vector = computed(() => dataService.getGeo(props.geo.type, props.geo.vectorId));
@@ -22,7 +30,8 @@ const clickHandlerFactory = (key) => {
   return () => drawRef.value.uiControl.updateVectorForSelectUI(key);
 };
 
-const lineTypeMenu = [
+const showChange = ref(false);
+const lineTypeMenu = reactive([
   {
     key: VectorStyle.SingleSolidLine,
     icon: "line_sf",
@@ -41,27 +50,6 @@ const lineTypeMenu = [
       style.value = VectorStyle.SingleDashedLine;
     },
   },
-  // {
-  //   hide: props.geo.type === VectorType.CurveRoadEdge,
-  //   key: VectorStyle.DoubleSolidLine,
-  //   icon: "line_df",
-  //   text: "双实线",
-  //   onClick: clickHandlerFactory(VectorStyle.DoubleSolidLine),
-  // },
-  // {
-  //   hide: props.geo.type === VectorType.CurveRoadEdge,
-  //   key: VectorStyle.DoubleDashedLine,
-  //   icon: "line_dd",
-  //   text: "双虚线",
-  //   onClick: clickHandlerFactory(VectorStyle.DoubleDashedLine),
-  // },
-  // {
-  //   hide: props.geo.type === VectorType.CurveRoadEdge,
-  //   key: VectorStyle.BrokenLine,
-  //   icon: "line_broken",
-  //   text: "折线",
-  //   onClick: clickHandlerFactory(VectorStyle.BrokenLine),
-  // },
   {
     key: VectorStyle.PointDrawLine,
     icon: "line_dot",
@@ -77,13 +65,12 @@ const lineTypeMenu = [
     text: "路缘线",
     onClick: () => {
       clickHandlerFactory(VectorStyle.RoadSide)();
-      // menus.value[1] = lineWidthMenu[0];
+      style.value = VectorStyle.RoadSide;
     },
   },
-  // {key: VectorStyle.Greenbelt, icon: "treelawn", text: "绿化带 ", onClick: clickHandlerFactory(VectorStyle.Greenbelt)},
-];
+]);
 
-const lineWidthMenu = [
+const lineWidthMenu = reactive([
   {
     key: VectorWeight.Bold,
     icon: "l_thick",
@@ -102,28 +89,17 @@ const lineWidthMenu = [
       menus.value[1] = lineWidthMenu[0];
     },
   },
-
-];
-
-const appendMenus =
-  props.geo.type === VectorType.CurveRoadEdge
-    ? [
-        // {
-        //   key: VectorEvents.AddCrossPoint,
-        //   icon: "control_a",
-        //   text: "加控制点",
-        //   onClick: clickHandlerFactory(VectorEvents.AddCrossPoint)
-        // },
-        // {
-        //   key: VectorEvents.MinusCrossPoint,
-        //   icon: "control_d",
-        //   text: "减控制点",
-        //   onClick: clickHandlerFactory(VectorEvents.MinusCrossPoint)
-        // },
-      ]
-    : [];
+  {
+    key: "setRoadEdageWidth",
+    icon: "l_thin",
+    text: "宽度",
+    desc: 0,
+    onClick: () => {
+      showChange.value = !showChange.value;
+    },
+  },
+]);
 const childMenus = ref<UnwrapRef<typeof menus>>();
-// console.log(vector.value)
 const menus = ref([
   {
     key: UITypeExtend.lineType,
@@ -134,9 +110,22 @@ const menus = ref([
     },
   },
   vector.value?.weight === VectorWeight.Bold ? lineWidthMenu[0] : lineWidthMenu[1],
-  ...appendMenus,
 ]);
 
+watchEffect(() => {
+  if (style.value === VectorStyle.RoadSide) {
+    menus.value[1] = lineWidthMenu[2];
+    lineWidthMenu[2].desc = vector.value.roadSide.width;
+  } else {
+    showChange.value = false;
+  }
+});
+watchEffect(() => {
+  if (style.value === VectorStyle.RoadSide) {
+    vector.value.setRoadSideWidth(lineWidthMenu[2].desc);
+  }
+});
+
 const active = computed(() =>
   toRaw(childMenus.value) === lineTypeMenu
     ? menus.value[0]