Browse Source

feat: 优化操作

bill 4 months ago
parent
commit
48f5c4b20c

File diff suppressed because it is too large
+ 1 - 1
public/icons/a_adapt.svg


File diff suppressed because it is too large
+ 1 - 1
public/icons/redo.svg


File diff suppressed because it is too large
+ 1 - 1
public/icons/undo.svg


+ 17 - 15
src/components/icon/icon.vue

@@ -1,19 +1,21 @@
 <template>
-  <svg
-    class="icon"
-    aria-hidden="true"
-    :style="{
-      fontSize: computedSize,
-      stroke: computedColor,
-      fill: computedColor,
-      display: 'inline-block',
-      verticalAlign: 'middle',
-    }"
-    :width="computedSize"
-    :height="computedSize"
-  >
-    <use :xlink:href="`#icon-${name}`" />
-  </svg>
+  <span>
+    <svg
+      class="icon"
+      aria-hidden="true"
+      :style="{
+        fontSize: computedSize,
+        stroke: computedColor,
+        fill: computedColor,
+        display: 'inline-block',
+        verticalAlign: 'middle',
+      }"
+      :width="computedSize"
+      :height="computedSize"
+    >
+      <use :xlink:href="`#icon-${name}`" />
+    </svg>
+  </span>
 </template>
 
 <script lang="ts" setup>

+ 10 - 1
src/core/components/line/index.ts

@@ -4,6 +4,7 @@ import { getMouseColors } from "@/utils/colors.ts";
 import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts";
 import { Transform } from "konva/lib/Util";
 import { themeColor } from "@/constant/help-style.ts";
+import { inRevise } from "@/utils/shared.ts";
 
 export { default as Component } from "./line.vue";
 export { default as TempComponent } from "./temp-line.vue";
@@ -63,7 +64,15 @@ export const interactiveToData: InteractiveTo<"line"> = ({
 };
 
 export const interactiveFixData: InteractiveFix<"line"> = ({ data, info }) => {
-  data.points = [...info.consumed, info.cur!];
+  const nv = [...info.consumed, info.cur!];
+  data.points.length = nv.length
+  for (let i = 0; i < nv.length; i++) {
+    if (inRevise(data.points[i], nv[i])) {
+      data.points[i] = nv[i]
+    }
+  }
+
+  // data.points = [...info.consumed, info.cur!];
   return data;
 };
 

+ 2 - 2
src/core/components/share/edit-line.vue

@@ -3,10 +3,10 @@
     ref="line"
     :config="{
       stroke: 'red',
-      strokeWidth: data.strokeWidth + 20,
+      strokeWidth: data.strokeWidth,
       opacity: 0,
       points: flatPositions(points),
-      hitStrokeWidth: data.strokeWidth + 10,
+      hitStrokeWidth: data.strokeWidth + 20,
     }"
   />
 </template>

+ 37 - 32
src/core/components/share/edit-polygon.vue

@@ -1,36 +1,41 @@
 <template>
-  <template v-if="status.hover && canEdit && !operMode.mulSelection">
-    <EditLine
-      :data="data"
-      :points="data.points"
-      :closed="closed"
-      :id="data.id"
-      :ndx="ndx"
-      v-for="(_, ndx) in closed ? data.points.length : data.points.length - 1"
-      @update:line="
-        (p) => {
-          emit('update:position', { ndx, val: p[0] });
-          emit('update:position', { ndx: (ndx + 1) % data.points.length, val: p[1] });
-        }
-      "
-      @dragend="emit('update')"
-    />
-  </template>
-
-  <template v-if="(status.hover || status.active || addMode) && !operMode.mulSelection">
-    <Point
-      v-for="(_, ndx) in data.points"
-      :size="data.strokeWidth + 6"
-      :points="data.points"
-      :ndx="ndx"
-      :closed="closed"
-      :id="data.id"
-      :disable="addMode"
-      :color="data.stroke"
-      @update:position="(p) => emit('update:position', { ndx, val: p })"
-      @dragend="emit('update')"
-    />
-  </template>
+  <v-group>
+    <template
+      v-if="status.hover && canEdit && !operMode.mulSelection && data.points.length > 2"
+    >
+      <EditLine
+        :data="data"
+        :points="data.points"
+        :closed="closed"
+        :id="data.id"
+        :ndx="ndx"
+        v-for="(_, ndx) in closed ? data.points.length : data.points.length - 1"
+        @update:line="
+          (p) => {
+            emit('update:position', { ndx, val: p[0] });
+            emit('update:position', { ndx: (ndx + 1) % data.points.length, val: p[1] });
+          }
+        "
+        @dragend="emit('update')"
+      />
+    </template>
+  </v-group>
+  <v-group>
+    <template v-if="(status.hover || status.active || addMode) && !operMode.mulSelection">
+      <Point
+        v-for="(_, ndx) in data.points"
+        :size="data.strokeWidth + 6"
+        :points="data.points"
+        :ndx="ndx"
+        :closed="closed"
+        :id="data.id"
+        :disable="addMode"
+        :color="data.stroke"
+        @update:position="(p) => emit('update:position', { ndx, val: p })"
+        @dragend="emit('update')"
+      />
+    </template>
+  </v-group>
 </template>
 
 <script lang="ts" setup>

+ 1 - 1
src/core/components/text/index.ts

@@ -1,6 +1,6 @@
 import { Transform } from "konva/lib/Util";
 import { Text } from "konva/lib/shapes/Text";
-import { themeColor, themeMouseColors } from "@/constant/help-style.ts";
+import { themeColor } from "@/constant/help-style.ts";
 import {
   BaseItem,
   generateSnapInfos,

+ 13 - 2
src/core/helper/compass.vue

@@ -15,7 +15,7 @@
 import TempIcon from "../components/icon/temp-icon.vue";
 import { PropertyUpdate, mergeDescribes } from "../html-mount/propertys/index.ts";
 import { computed, ref, watch } from "vue";
-import { themeColor, themeMouseColors } from "@/constant/help-style.ts";
+import { themeMouseColors } from "@/constant/help-style.ts";
 import { useAnimationMouseStyle } from "../hook/use-mouse-status.ts";
 import { Group } from "konva/lib/Group";
 import { DC } from "@/deconstruction.js";
@@ -84,11 +84,22 @@ describes.rotate = {
 
 const size = useResize();
 const viewerConfig = useViewerTransformConfig();
+const margin = computed(() => {
+  let margin = config.margin || 0;
+  if (!Array.isArray(margin)) {
+    margin = [margin, margin, margin, margin];
+  }
+  return margin;
+});
 const mat = computed(() => {
   const tf = new Transform();
   if (!size.value) return tf.m;
 
-  const pos = getFixPosition({ right: 20, top: 20 }, data.value, size.value);
+  const pos = getFixPosition(
+    { right: 20 + margin.value[1], top: 20 + margin.value[0] },
+    data.value,
+    size.value
+  );
   pos.x += data.value.width / 2;
   pos.y += data.value.height / 2;
   return tf

+ 1 - 2
src/core/helper/layers.vue

@@ -20,7 +20,6 @@
 import TempIcon from "../components/icon/temp-icon.vue";
 import HoverTriggle from "../html-mount/hover-triggle.vue";
 import { computed, ref } from "vue";
-import { themeMouseColors } from "@/constant/help-style.ts";
 import { getMouseColors } from "@/utils/colors.ts";
 import { useAnimationMouseStyle } from "../hook/use-mouse-status.ts";
 import { Group } from "konva/lib/Group";
@@ -39,7 +38,7 @@ const data = ref({
   height: 20,
   rotation: 0,
   // stroke: themeMouseColors.pub,
-  fill: themeMouseColors.pub,
+  fill: "#000000",
   url: "/icons/grouping.svg",
 });
 const shape = ref<DC<Group>>();

+ 17 - 1
src/core/hook/use-debugger.ts

@@ -1,7 +1,23 @@
-import { ref } from "vue";
+import { onBeforeUpdate, onMounted, onUpdated, ref } from "vue";
 import { installGlobalVar } from "./use-global-vars";
 import { Pos } from "@/utils/math";
+import { DrawItem } from "../components";
 
 export const useTestPoints = installGlobalVar(() => {
   return ref<Pos[]>([]);
 });
+
+
+export const useMeasure = <T extends DrawItem>(data: T) => {
+  if (!import.meta.env.DEV) return;
+  onBeforeUpdate(() => {
+    console.time('updated' + data.id);
+  });
+  onUpdated(() => {
+    console.timeEnd('updated' + data.id);
+  });
+  console.time('mounted' + data.id);
+  onMounted(() => {
+    console.timeEnd('mounted' + data.id);
+  });
+}

+ 1 - 1
src/core/hook/use-draw.ts

@@ -10,7 +10,7 @@ import {
   useInteractiveProps,
 } from "./use-interactive";
 import { Mode } from "@/constant/mode";
-import { copy, mergeFuns } from "@/utils/shared";
+import { copy, debounce, mergeFuns } from "@/utils/shared";
 import {
   Components,
   components,

+ 2 - 1
src/core/hook/use-transformer.ts

@@ -1,5 +1,5 @@
 import { useMouseShapeStatus } from "./use-mouse-status.ts";
-import { nextTick, Ref, ref, toRaw, watch } from "vue";
+import {  Ref, ref, toRaw, watch } from "vue";
 import { DC, EntityShape } from "../../deconstruction";
 import {
   installGlobalVar,
@@ -196,6 +196,7 @@ export const useShapeDrag = (shape: Ref<DC<EntityShape> | undefined>) => {
         start = position;
         if (!can.dragMode) return;
         mode.add(Mode.draging);
+        console.log(shape)
         transformIngShapes.value.push(shape);
       }
     };

+ 0 - 2
src/core/html-mount/hover-triggle.vue

@@ -53,10 +53,8 @@ const mode = useMode();
 watchEffect((onCleanup) => {
   const dom = stage.value?.getStage().container();
   if (!dom || mode.value.has(Mode.draw)) return;
-  console.log("moveHandler");
   dom.addEventListener("mousemove", updateShow);
   onCleanup(() => {
-    console.log("cancelMoveHandler");
     dom.removeEventListener("mousemove", updateShow);
   });
 });

+ 1 - 2
src/core/renderer/draw-group.vue

@@ -1,6 +1,4 @@
 <template>
-  <!-- :real="store.getItemById(item.id)"
-  temp -->
   <ShapeComponent
     :data="(item as any)"
     v-for="item in tempItems"
@@ -17,4 +15,5 @@ const props = defineProps<{ type: ShapeType }>();
 const tempItems = useInteractiveAdd(props.type);
 const type = props.type;
 const ShapeComponent = components[type].TempComponent || components[type].Component;
+
 </script>

+ 1 - 1
src/core/renderer/draw-shape.vue

@@ -3,7 +3,7 @@
 </template>
 
 <script lang="ts" setup>
-import { computed, onUnmounted, watch, watchEffect } from "vue";
+import { computed, onUnmounted, watch } from "vue";
 import { ComponentSnapInfo, DrawItem } from "../components";
 import { useStore } from "../store";
 import { components } from "../components";

+ 0 - 14
src/example/components/container/container.vue

@@ -75,12 +75,6 @@ defineExpose({
   --left: 0px;
   overflow: hidden;
 
-  .header {
-    margin-top: var(--top);
-    transition: margin-top 0.3s ease;
-    height: global.$headerSize;
-    flex: 0 0 auto;
-  }
 
   .container {
     flex: 1;
@@ -88,14 +82,6 @@ defineExpose({
     align-items: stretch;
   }
 
-  .slide {
-    flex: 0 0 auto;
-    width: global.$slideSize;
-    margin-left: var(--left);
-    background: #fff;
-    transition: margin-left 0.3s ease;
-  }
-
   .content {
     position: relative;
     width: calc(100% - 70px - var(--left));

+ 3 - 3
src/example/components/header/actions.ts

@@ -1,4 +1,4 @@
-import { reactive } from "vue";
+import { computed, reactive } from "vue";
 import { Draw } from "../container/use-draw";
 import { animation } from "@/core/hook/use-animation";
 import saveAs from "@/utils/file-serve";
@@ -38,13 +38,13 @@ export const getHeaderActions = (draw: Draw) => {
       handler: () => draw.history.undo(),
       text: "撤销",
       icon: "undo",
-      disabled: !draw.history.hasUndo.value,
+      disabled: computed(() => !draw.history.hasUndo.value),
     }),
     redo: reactive({
       handler: () => draw.history.redo(),
       text: "重做",
       icon: "redo",
-      disabled: !draw.history.hasRedo.value,
+      disabled: computed(() => !draw.history.hasRedo.value),
     }),
     clear: reactive({
       handler: () => draw.store.clear(),

+ 7 - 2
src/example/components/header/index.vue

@@ -55,6 +55,7 @@ defineProps<{ actionGroups: ActionGroups; title?: string; noBack?: boolean }>();
 
 <style lang="scss" scoped>
 @use 'element-plus/theme-chalk/src/common/var';
+@use '../../styles/global';
 
 .header {
   background-color: #fff;
@@ -64,6 +65,10 @@ defineProps<{ actionGroups: ActionGroups; title?: string; noBack?: boolean }>();
   justify-content: space-between;
   color: rgba(0, 0, 0, 0.85);
   border-bottom: 1px solid #e6e6e6;
+  margin-top: var(--top);
+  transition: margin-top 0.3s ease;
+  height: global.$headerSize;
+  flex: 0 0 auto;
 }
 
 .draw-operate {
@@ -82,9 +87,9 @@ defineProps<{ actionGroups: ActionGroups; title?: string; noBack?: boolean }>();
       top: 50%;
       transform: translateY(-50%);
       position: absolute;
-      height: 1em;
+      height: 0.7em;
       width: 1px;
-      background: currentColor;
+      background: rgba(0, 0, 0, 0.3);
     }
   }
 

+ 12 - 11
src/example/components/show-vr.vue

@@ -2,18 +2,16 @@
   <div class="vr" :style="{ width: width + 'px', height: height + 'px' }" ref="vrRef">
     <div class="header" ref="headerRef">
       <span>VR全景</span>
-      <el-icon class="close" @click="$emit('close')"><Close /></el-icon>
+      <Icon class="close" name="close" @click="$emit('close')" />
     </div>
     <div class="content" :style="{ pointerEvents: downPos ? 'none' : 'all' }">
       <iframe :src="tempStrFill(SceneTypeTempUrls[scene.type], scene)" />
-      <el-icon class="full" @click="fullHandler"><FullScreen /></el-icon>
+      <Icon class="full" name="close" @click="fullHandler" />
     </div>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { ElIcon } from "element-plus";
-import { Close, FullScreen } from "@element-plus/icons-vue";
 import { dragListener, listener } from "@/utils/event";
 import { onUnmounted, ref, watch, watchEffect } from "vue";
 import { Pos } from "@/utils/math";
@@ -25,8 +23,8 @@ defineEmits<{ (e: "close"): void }>();
 
 const headerRef = ref<HTMLDivElement>();
 const vrRef = ref<HTMLDivElement>();
-const width = ref(295);
-const height = ref(175);
+const width = ref(320);
+const height = ref(220);
 
 let isFull = false;
 const fullHandler = () => {
@@ -100,20 +98,24 @@ defineExpose({ refresh: initMoveHandler });
   z-index: 1;
   display: flex;
   flex-direction: column;
+  border-radius: 4px;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
 
   .header {
-    height: 25px;
+    height: 40px;
     flex: 0 0 auto;
+
     display: flex;
     cursor: move;
     align-items: center;
     justify-content: space-between;
-    padding: 0 5px;
+    padding: 0 16px;
     font-size: 14px;
+    color: #000;
 
     .close {
       color: #000;
-      font-size: 16px;
+      font-size: 22px;
       cursor: pointer;
     }
   }
@@ -122,13 +124,12 @@ defineExpose({ refresh: initMoveHandler });
     flex: 1;
     position: relative;
     .full {
-      box-shadow: 0 0 5px #000;
       right: 5px;
       bottom: 5px;
+      font-size: 22px;
       color: #fff;
       position: absolute;
       cursor: pointer;
-      font-size: 18px;
     }
   }
   iframe {

+ 2 - 1
src/example/components/slide/slide-item.vue

@@ -24,6 +24,7 @@ defineProps<{ data: MenuItem }>();
 
 <style lang="scss">
 .is-active .menu-layout {
-  background: var(--el-menu-hover-bg-color);
+  background: var(--el-color-primary-light-7);
+  // background: rgba(88,185,234,0.3);
 }
 </style>

+ 5 - 1
src/example/components/slide/slide.vue

@@ -65,7 +65,11 @@ const openHandler = (value: string) => {
 @use '../../styles/global';
 
 .slide {
-  margin-left: 0;
+  flex: 0 0 auto;
+  width: global.$slideSize;
+  margin-left: var(--left);
+  background: #fff;
+  transition: margin-left 0.3s ease;
   &.hide {
     transform: translateX(-100%);
   }

+ 9 - 4
src/example/dialog/ai/ai.vue

@@ -1,8 +1,8 @@
 <template>
   <div style="padding: 20px 20px 40px">
-    <VR v-model:value="scene" class="vr-layout" />
+    <VR v-model:value="scene" class="vr-layout" label="(含平面图和AI绘图)" />
     <div v-if="scene" class="tagging-layout">
-      <span>请选择图例范围</span>
+      <p class="title">请选择图例范围</p>
       <el-checkbox-group v-model="syncTags" style="width: 200px">
         <el-checkbox
           :label="item.label"
@@ -30,7 +30,7 @@ const scene = ref<Scene>();
 const options = {
   [SCENE_TYPE.mesh]: [
     { value: "signage", label: "指示牌" },
-    { value: "hot", label: "多媒体标签" },
+    // { value: "hot", label: "多媒体标签" },
   ],
   [SCENE_TYPE.cloud]: [{ value: "hot", label: "热点" }],
   [SCENE_TYPE.fuse]: [{ value: "hot", label: "标签" }],
@@ -59,6 +59,11 @@ defineExpose({
   padding: 0 !important;
 }
 .tagging-layout {
-  margin-top: 20px;
+  margin-top: 24px;
+}
+.title {
+  font-size: 14px;
+  color: rgba(0, 0, 0, 0.85);
+  margin: 0;
 }
 </style>

+ 2 - 2
src/example/dialog/ai/index.ts

@@ -1,6 +1,6 @@
 import { markRaw, reactive } from "vue";
 import AI from "./ai.vue";
-import { SceneFloors, Tagings } from "../../platform-resource";
+import { SceneFloors, Tagings } from "../../platform/platform-resource";
 
 type Props = {
   title: string;
@@ -22,7 +22,7 @@ export const props = reactive({
 export const selectAI = () =>
   new Promise<AIExposeData>((resolve, reject) => {
     props.content = markRaw(AI);
-    props.title = "AI导入";
+    props.title = "请选择场景";
     props.visiable = true;
     props.submit = (info) => {
       resolve(info);

+ 20 - 2
src/example/dialog/vr/vr.vue

@@ -1,12 +1,15 @@
 <template>
   <div style="padding: 20px 20px 40px">
+    <p class="title">
+      请选择场景<span v-if="label">{{ label }}</span>
+    </p>
     <el-select
       :model-value="value?.id"
       @update:model-value="(id) => (value = scenes.find((scene) => scene.id === id))"
       filterable
       remote
       reserve-keyword
-      placeholder="请选择场景"
+      placeholder="请输入"
       clearable
       :remote-method="searchSenects"
       remote-show-suffix
@@ -29,7 +32,7 @@ import { asyncTimeout } from "@/utils/shared";
 import { Scene, SCENE_TYPE, SceneTypeNames } from "../../platform/platform-resource";
 import { getMeshSceneList } from "./test";
 
-const props = defineProps<{ value?: Scene }>();
+const props = defineProps<{ value?: Scene; label: string }>();
 const emit = defineEmits<{ (e: "update:value", val: Scene): void }>();
 
 const _value = ref<Scene>();
@@ -85,3 +88,18 @@ defineExpose({
   submit: () => value.value,
 });
 </script>
+
+<style lang="scss" scoped>
+.title {
+  margin-bottom: 10px;
+  font-size: 14px;
+  color: rgba(0, 0, 0, 0.85);
+  line-height: 22px;
+
+  span {
+    font-size: 12px;
+    color: rgba(0, 0, 0, 0.45);
+    line-height: 18px;
+  }
+}
+</style>

+ 4 - 4
src/example/platform/platform-draw.ts

@@ -1,6 +1,6 @@
 import { genBound } from "@/utils/shared";
-import { AIExposeData } from "./dialog/ai";
-import { Draw } from "../fuse/views/use-draw";
+import { AIExposeData } from "../dialog/ai";
+import { Draw } from "../components/container/use-draw";
 import { SceneFloor } from "./platform-resource";
 import { getBaseItem } from "@/core/components/util";
 import { LineData } from "@/core/components/line";
@@ -93,11 +93,11 @@ const drawLayerResource = (
   const createTime = Date.now()
 
   const geos: LineData[] = [];
-  layerResource.geos.forEach((item) => {
+  layerResource.geos.forEach((item, ndx) => {
     bound.update(item);
     geos.push({
       ...getBaseItem(),
-      createTime: createTime,
+      createTime: createTime + ndx,
       lock: import.meta.env.DEV ? false : true,
       attitude: [1, 0, 0, 1, 0, 0],
       points: item,

+ 1 - 1
src/example/styles/global.scss

@@ -1,6 +1,6 @@
 @use 'element-plus/theme-chalk/src/common/var';
 
-$headerSize: 70px;
+$headerSize: 60px;
 $slideSize: 64px;
 
 * {