Parcourir la source

feat: 优化默认样式

bill il y a 3 mois
Parent
commit
4176757b8f
68 fichiers modifiés avec 620 ajouts et 293 suppressions
  1. 0 1
      package.json
  2. 0 3
      pnpm-lock.yaml
  3. 1 0
      public/icons/pic_yes.svg
  4. 17 6
      src/core/components/arrow/arrow.vue
  5. 4 1
      src/core/components/arrow/index.ts
  6. 4 0
      src/core/components/arrow/temp-arrow.vue
  7. 2 1
      src/core/components/circle/circle.vue
  8. 9 3
      src/core/components/circle/index.ts
  9. 0 3
      src/core/components/group/group.vue
  10. 1 0
      src/core/components/icon/icon.vue
  11. 9 2
      src/core/components/icon/index.ts
  12. 1 0
      src/core/components/image/image.vue
  13. 1 2
      src/core/components/image/index.ts
  14. 1 2
      src/core/components/image/temp-image.vue
  15. 1 0
      src/core/components/index.ts
  16. 2 1
      src/core/components/line/index.ts
  17. 2 5
      src/core/components/line/line.vue
  18. 1 1
      src/core/components/polygon/index.ts
  19. 14 3
      src/core/components/polygon/polygon.vue
  20. 4 0
      src/core/components/polygon/temp-polygon.vue
  21. 7 3
      src/core/components/rectangle/index.ts
  22. 2 1
      src/core/components/rectangle/rectangle.vue
  23. 5 0
      src/core/components/serial/index.ts
  24. 2 1
      src/core/components/serial/serial.vue
  25. 6 4
      src/core/components/share/text-area.vue
  26. 3 1
      src/core/components/share/text.vue
  27. 8 1
      src/core/components/table/index.ts
  28. 6 53
      src/core/components/table/table.vue
  29. 8 2
      src/core/components/text/index.ts
  30. 10 5
      src/core/components/text/text.vue
  31. 9 5
      src/core/components/triangle/index.ts
  32. 2 1
      src/core/components/triangle/triangle.vue
  33. 3 1
      src/core/components/util.ts
  34. 0 4
      src/core/helper/layers.vue
  35. 11 17
      src/core/hook/use-component.ts
  36. 4 7
      src/core/hook/use-draw.ts
  37. 14 5
      src/core/hook/use-expose.ts
  38. 0 1
      src/core/hook/use-paste.ts
  39. 1 1
      src/core/hook/use-transformer.ts
  40. 53 0
      src/core/html-mount/propertys/components/color-free.vue
  41. 69 39
      src/core/html-mount/propertys/components/color.vue
  42. 11 1
      src/core/html-mount/propertys/components/num.vue
  43. 11 2
      src/core/html-mount/propertys/components/proportion.vue
  44. 1 2
      src/core/html-mount/propertys/components/select.vue
  45. 39 20
      src/core/html-mount/propertys/describes.json
  46. 10 13
      src/core/html-mount/propertys/hover-operate.vue
  47. 1 0
      src/core/html-mount/propertys/index.ts
  48. 87 27
      src/core/html-mount/propertys/mount.vue
  49. 1 1
      src/core/renderer/group.vue
  50. 2 3
      src/core/renderer/renderer.vue
  51. 1 2
      src/core/store/store.ts
  52. 28 2
      src/example/components/container/container.vue
  53. 17 1
      src/example/components/header/actions.ts
  54. 4 4
      src/example/components/show-vr.vue
  55. 3 4
      src/example/components/slide/actions.ts
  56. 1 1
      src/example/dialog/ai/index.ts
  57. 1 2
      src/example/dialog/basemap/gd-map/selectAMapImage.vue
  58. 1 1
      src/example/dialog/vr/vr.vue
  59. 5 9
      src/example/fuse/router.ts
  60. 3 1
      src/example/fuse/views/overview/header.vue
  61. 0 1
      src/example/fuse/views/overview/index.vue
  62. 41 0
      src/example/fuse/views/overview/query.vue
  63. 5 2
      src/example/fuse/views/tabulation/gen.ts
  64. 3 0
      src/example/fuse/views/tabulation/header.vue
  65. 1 7
      src/example/fuse/views/tabulation/index.vue
  66. 43 0
      src/example/fuse/views/tabulation/query.vue
  67. 1 0
      src/example/styles/global.scss
  68. 2 1
      src/utils/resource.ts

+ 0 - 1
package.json

@@ -10,7 +10,6 @@
   },
   "dependencies": {
     "@amap/amap-jsapi-loader": "^1.0.1",
-    "@element-plus/icons-vue": "^2.3.1",
     "@tweenjs/tween.js": "^25.0.0",
     "@types/node": "^22.9.0",
     "@types/three": "^0.169.0",

+ 0 - 3
pnpm-lock.yaml

@@ -11,9 +11,6 @@ importers:
       '@amap/amap-jsapi-loader':
         specifier: ^1.0.1
         version: 1.0.1
-      '@element-plus/icons-vue':
-        specifier: ^2.3.1
-        version: 2.3.1(vue@3.5.13(typescript@5.6.3))
       '@tweenjs/tween.js':
         specifier: ^25.0.0
         version: 25.0.0

Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
public/icons/pic_yes.svg


+ 17 - 6
src/core/components/arrow/arrow.vue

@@ -4,14 +4,17 @@
     :ref="(v: any) => shape = v?.shape"
     :id="data.id"
     @update:position="updatePosition"
-    canEdit
+    @addPoint="addPoint"
+    @deletePoint="deletePoint"
     @update="emit('updateShape', { ...data })"
+    canEdit
   />
   <PropertyUpdate
     :describes="describes"
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate :target="shape" :menus="operateMenus" />
 </template>
@@ -22,13 +25,12 @@ import { ArrowData, getMouseStyle, defaultStyle, matResponse } from "./index.ts"
 import { TempComponent } from "./";
 import { useComponentStatus } from "@/core/hook/use-component.ts";
 import { Line } from "konva/lib/shapes/Line";
-import { Transform } from "konva/lib/Util";
 import { Pos } from "@/utils/math.ts";
 import { Group } from "konva/lib/Group";
 import { flatPositions } from "@/utils/shared.ts";
 import { useInteractiveDrawShapeAPI } from "@/core/hook/use-draw.ts";
 import { useStore } from "@/core/store/index.ts";
-import { EditPen } from "@element-plus/icons-vue";
+import { themeColor } from "@/constant/help-style.ts";
 
 const props = defineProps<{ data: ArrowData }>();
 const emit = defineEmits<{
@@ -42,6 +44,16 @@ const updatePosition = ({ ndx, val }: { ndx: number; val: Pos }) => {
   shape.value?.getNode().fire("bound-change");
 };
 
+const deletePoint = (ndx: number) => {
+  data.value.points.splice(ndx, 1);
+  shape.value?.getNode().fire("bound-change");
+};
+
+const addPoint = ({ ndx, val }: { ndx: number; val: Pos }) => {
+  data.value.points.splice(ndx + 1, 0, val);
+  shape.value?.getNode().fire("bound-change");
+};
+
 const { shape, tData, operateMenus, describes, data } = useComponentStatus<
   Group,
   ArrowData
@@ -56,7 +68,7 @@ const { shape, tData, operateMenus, describes, data } = useComponentStatus<
   transformType: "line",
   getRepShape(): Line {
     return new Line({
-      fill: "rgb(0, 255, 0)",
+      fill: themeColor,
       visible: false,
       strokeWidth: 0,
       points: flatPositions(data.value.points),
@@ -70,7 +82,7 @@ const { shape, tData, operateMenus, describes, data } = useComponentStatus<
     "pointerPosition",
     "strokeWidth",
     "pointerLength",
-    "dash",
+    // "dash",
     // "ref",
     "opacity",
     // "zIndex",
@@ -81,7 +93,6 @@ const draw = useInteractiveDrawShapeAPI();
 const store = useStore();
 operateMenus.push({
   label: "钢笔编辑",
-  icon: EditPen,
   handler() {
     draw.enterDrawShape("arrow", {
       ...props.data,

+ 4 - 1
src/core/components/arrow/index.ts

@@ -23,10 +23,12 @@ export const defaultStyle = {
   pointerLength: 10,
 };
 
+// export const fill
+
 export const addMode = "dots";
 
 export const getMouseStyle = (data: ArrowData) => {
-  const strokeStatus = getMouseColors(data.fill || themeColor);
+  const strokeStatus = getMouseColors(data.fill || defaultStyle.fill);
   const strokeWidth = data.strokeWidth || defaultStyle.strokeWidth;
 
   return {
@@ -71,6 +73,7 @@ export const interactiveToData: InteractiveTo<"arrow"> = ({
       data: {
         ...getBaseItem(),
         ...preset,
+        ...defaultStyle,
         id: onlyId(),
         points: [],
         attitude: [1, 0, 0, 1, 0, 0],

+ 4 - 0
src/core/components/arrow/temp-arrow.vue

@@ -25,6 +25,8 @@
       :canEdit="canEdit"
       @update:position="(data) => emit('update:position', data)"
       @update="emit('update')"
+      @deletePoint="(ndx) => emit('deletePoint', ndx)"
+        @addPoint="(data) => emit('addPoint', data)"
       v-if="shape"
     />
 
@@ -54,6 +56,8 @@ const props = defineProps<{ data: ArrowData; canEdit?: boolean; addMode?: boolea
 const emit = defineEmits<{
   (e: "update:position", data: { ndx: number; val: Pos }): void;
   (e: "update"): void;
+  (e: "deletePoint", ndx: number): void;
+  (e: "addPoint", data: { ndx: number; val: Pos }): void;
 }>();
 
 const shape = ref<DC<Group>>();

+ 2 - 1
src/core/components/circle/circle.vue

@@ -11,6 +11,7 @@
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate :target="shape" :menus="operateMenus" />
 </template>
@@ -82,7 +83,7 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus<
     "fontSize",
     // "ref",
     "opacity",
-    "dash",
+    // "dash",
     //  "zIndex"
     "align",
     "fontStyle",

+ 9 - 3
src/core/components/circle/index.ts

@@ -22,7 +22,6 @@ export const defaultStyle = {
   strokeWidth: 2,
   fontSize: 16,
   align: "center",
-  fill: '#ffffff',
   fontStyle: "normal",
   fontColor: '#000000',
   padding: 8
@@ -32,10 +31,10 @@ export const addMode = "area";
 
 export const getMouseStyle = (data: CircleData) => {
   const fillStatus = data.fill && getMouseColors(data.fill);
-  const strokeStatus = getMouseColors(data.stroke || themeColor);
+  const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
   const strokeWidth = data.strokeWidth || defaultStyle.strokeWidth;
   return {
-    default: { fill: fillStatus && defaultStyle.fill, stroke: data.stroke || defaultStyle.stroke, strokeWidth },
+    default: {  stroke: data.stroke || defaultStyle.stroke, strokeWidth },
     hover: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus.hover },
     select: { fill: fillStatus && fillStatus.select, stroke: strokeStatus.select  },
     focus: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus.hover },
@@ -81,6 +80,7 @@ export const interactiveToData: InteractiveTo<'circle'> = ({
 }) => {
   if (info.cur) {
     const item = {
+      ...defaultStyle,
       ...getBaseItem(),
       ...preset,
     } as unknown as CircleData;
@@ -122,4 +122,10 @@ if (!initRadius) {
     .translate(dec.x, dec.y)
     .rotate(MathUtils.degToRad(dec.rotation)).m;
   return data;
+}
+
+export const getPredefine = (key: keyof CircleData) => {
+  if (key === 'fill') {
+    return { canun: true }
+  }
 }

+ 0 - 3
src/core/components/group/group.vue

@@ -24,7 +24,6 @@ import { useHistory } from "@/core/hook/use-history.ts";
 import { computed, nextTick, onUnmounted, ref, shallowRef, watchEffect } from "vue";
 import { useOperMode } from "@/core/hook/use-status.ts";
 import { EntityShape } from "@/deconstruction.js";
-import { Top } from "@element-plus/icons-vue";
 import { getBaseItem } from "../util.ts";
 import { useForciblyShowItemIds } from "@/core/hook/use-global-vars.ts";
 import { themeColor } from "@/constant/help-style.ts";
@@ -136,7 +135,6 @@ watchEffect(() => {
     operateMenus.value = [
       {
         label: `解除分组`,
-        icon: Top,
         handler() {
           emit("delShape");
         },
@@ -146,7 +144,6 @@ watchEffect(() => {
     operateMenus.value = [
       {
         label: `添加分组`,
-        icon: Top,
         handler() {
           emit("addShape", {
             ...props.data,

+ 1 - 0
src/core/components/icon/icon.vue

@@ -4,6 +4,7 @@
     :describes="describes"
     :data="data"
     :target="shape"
+    @delete="emit('delShape')"
     @change="emit('updateShape', { ...data })"
   />
   <Operate :target="shape" :menus="operateMenus" />

+ 9 - 2
src/core/components/icon/index.ts

@@ -1,4 +1,4 @@
-import { themeColor, themeMouseColors } from "@/constant/help-style.ts";
+import { themeColor } from "@/constant/help-style.ts";
 import { Transform } from "konva/lib/Util";
 import {
   BaseItem,
@@ -38,7 +38,7 @@ export const getSnapPoints = (data: IconData) => {
 };
 
 export const getMouseStyle = (data: IconData) => {
-  const fillStatus = getMouseColors(data.coverFill || themeColor);
+  const fillStatus = getMouseColors(data.coverFill || defaultStyle.coverFill);
   const hCoverOpcaoty = data.coverOpcatiy ? data.coverOpcatiy : 0.3;
 
   return {
@@ -117,4 +117,11 @@ export const interactiveFixData: InteractiveFix<"icon"> = ({
 export const matResponse = ({data, mat, increment}: MatResponseProps<'icon'>) => {
   data.mat = increment ? mat.copy().multiply(new Transform(data.mat)).m : mat.m;
   return data;
+}
+
+
+export const getPredefine = (key: keyof IconData) => {
+  if (key === 'fill' || key === 'stroke') {
+    return { canun: true }
+  }
 }

+ 1 - 0
src/core/components/image/image.vue

@@ -5,6 +5,7 @@
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate :target="shape" :menus="operateMenus" />
 </template>

+ 1 - 2
src/core/components/image/index.ts

@@ -9,7 +9,6 @@ import { getMouseColors } from "@/utils/colors.ts";
 import { imageInfo } from "@/utils/resource.ts";
 import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts";
 import { Size } from "@/utils/math.ts";
-import { themeColor } from "@/constant/help-style.ts";
 
 export { default as Component } from "./image.vue";
 export { default as TempComponent } from "./temp-image.vue";
@@ -23,7 +22,7 @@ export const defaultStyle = {
 export const addMode = "dot";
 
 export const getMouseStyle = (data: ImageData) => {
-  const strokeStatus = getMouseColors(data.stroke || themeColor);
+  const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
 
   return {
     default: { stroke: data.stroke || defaultStyle.stroke },

+ 1 - 2
src/core/components/image/temp-image.vue

@@ -37,7 +37,6 @@ watch(
   async (url) => {
     image.value = null;
     image.value = await getImage(url);
-    image.value.crossOrigin = "anonymous";
   },
   { immediate: true }
 );
@@ -46,7 +45,6 @@ const size = useViewSize();
 const config = computed(() => {
   let w = data.value.width;
   let h = data.value.height;
-
   // 认为是百分比
   if (image.value && size.value && (w <= 1 || h <= 1)) {
     w = w <= 1 ? size.value.width * w : w;
@@ -75,4 +73,5 @@ const groupConfig = computed(() => {
     ...new Transform(data.value.mat).decompose(),
   };
 });
+
 </script>

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

@@ -51,6 +51,7 @@ export type Components = {
   [key in keyof typeof _components]: (typeof _components)[key] & {
     getSnapInfos?: (items: DrawItem<key>) => ComponentSnapInfo[];
     GroupComponent: (props: { data: DrawItem[] }) => any;
+    getPredefine?: (attrKey: keyof DrawItem<key>) => any
   };
 };
 export type ComponentValue<

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

@@ -19,7 +19,7 @@ export const defaultStyle = {
 export const addMode = "dots";
 
 export const getMouseStyle = (data: LineData) => {
-  const strokeStatus = getMouseColors(data.stroke || themeColor);
+  const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
   const strokeWidth = data.strokeWidth || defaultStyle.strokeWidth;
 
   return {
@@ -54,6 +54,7 @@ export const interactiveToData: InteractiveTo<"line"> = ({
       ...args,
       info,
       data: {
+        ...defaultStyle,
         ...getBaseItem(),
         ...preset,
         points: [],

+ 2 - 5
src/core/components/line/line.vue

@@ -14,6 +14,7 @@
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate :target="shape" :menus="operateMenus" />
 </template>
@@ -23,11 +24,9 @@ import { LineData, getMouseStyle, defaultStyle, matResponse } from "./index.ts";
 import { useComponentStatus } from "@/core/hook/use-component.ts";
 import { PropertyUpdate, Operate } from "../../html-mount/propertys/index.ts";
 import TempLine from "./temp-line.vue";
-import { EditPen } from "@element-plus/icons-vue";
 import { useInteractiveDrawShapeAPI } from "@/core/hook/use-draw.ts";
 import { useStore } from "@/core/store/index.ts";
 import { Pos } from "@/utils/math.ts";
-import { de } from "element-plus/es/locale/index.mjs";
 
 const props = defineProps<{ data: LineData }>();
 const emit = defineEmits<{
@@ -52,7 +51,7 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus({
   propertys: [
     "stroke",
     "strokeWidth",
-    "dash",
+    // "dash",
     "opacity",
     //  "ref", "zIndex"
   ],
@@ -69,7 +68,6 @@ const deletePoint = (ndx: number) => {
 };
 
 const addPoint = ({ ndx, val }: { ndx: number; val: Pos }) => {
-  console.log(ndx, val);
   data.value.points.splice(ndx + 1, 0, val);
   shape.value?.getNode().fire("bound-change");
 };
@@ -78,7 +76,6 @@ const draw = useInteractiveDrawShapeAPI();
 const store = useStore();
 operateMenus.push({
   label: "钢笔编辑",
-  icon: EditPen,
   handler() {
     draw.enterDrawShape("line", {
       ...props.data,

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

@@ -19,7 +19,7 @@ export const defaultStyle = {
 
 export const getMouseStyle = (data: PolygonData) => {
   const fillStatus = data.fill && getMouseColors(data.fill);
-  const strokeStatus = getMouseColors(data.stroke || themeColor);
+  const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
   const strokeWidth = data.strokeWidth || defaultStyle.strokeWidth;
 
   return {

+ 14 - 3
src/core/components/polygon/polygon.vue

@@ -4,6 +4,8 @@
     :ref="(v: any) => shape = v?.shape"
     :id="data.id"
     @update:position="updatePosition"
+    @deletePoint="deletePoint"
+    @addPoint="addPoint"
     can-edit
     @update="emit('updateShape', { ...data })"
   />
@@ -12,6 +14,7 @@
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate :target="shape" :menus="operateMenus" />
 </template>
@@ -23,7 +26,6 @@ import { PropertyUpdate, Operate } from "../../html-mount/propertys/index.ts";
 import TempLine from "./temp-polygon.vue";
 import { useInteractiveDrawShapeAPI } from "@/core/hook/use-draw.ts";
 import { useStore } from "@/core/store/index.ts";
-import { EditPen } from "@element-plus/icons-vue";
 import { Pos } from "@/utils/math.ts";
 
 const props = defineProps<{ data: PolygonData }>();
@@ -49,7 +51,7 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus({
     "fill",
     "stroke",
     "strokeWidth",
-    "dash",
+    // "dash",
     "opacity",
     //  "ref", "zIndex"
   ],
@@ -60,11 +62,20 @@ const updatePosition = ({ ndx, val }: { ndx: number; val: Pos }) => {
   shape.value?.getNode().fire("bound-change");
 };
 
+const deletePoint = (ndx: number) => {
+  data.value.points.splice(ndx, 1);
+  shape.value?.getNode().fire("bound-change");
+};
+
+const addPoint = ({ ndx, val }: { ndx: number; val: Pos }) => {
+  data.value.points.splice(ndx + 1, 0, val);
+  shape.value?.getNode().fire("bound-change");
+};
+
 const draw = useInteractiveDrawShapeAPI();
 const store = useStore();
 operateMenus.push({
   label: "钢笔编辑",
-  icon: EditPen,
   handler() {
     draw.enterDrawShape("polygon", {
       ...props.data,

+ 4 - 0
src/core/components/polygon/temp-polygon.vue

@@ -19,6 +19,8 @@
       :canEdit="canEdit"
       @update:position="(data) => emit('update:position', data)"
       @update="emit('update')"
+      @deletePoint="(ndx) => emit('deletePoint', ndx)"
+      @addPoint="(data) => emit('addPoint', data)"
       v-if="shape"
     />
     <!-- status.hover -->
@@ -45,7 +47,9 @@ import { useConfig } from "@/core/hook/use-config.ts";
 const props = defineProps<{ data: PolygonData; canEdit?: boolean; addMode?: boolean }>();
 const emit = defineEmits<{
   (e: "update:position", data: { ndx: number; val: Pos }): void;
+  (e: "addPoint", data: { ndx: number; val: Pos }): void;
   (e: "update"): void;
+  (e: "deletePoint", ndx: number): void;
 }>();
 
 const data = computed(() => ({ ...defaultStyle, ...props.data }));

+ 7 - 3
src/core/components/rectangle/index.ts

@@ -13,7 +13,6 @@ export const shapeName = "矩形";
 export const defaultStyle = {
   dash: [30, 0],
   strokeWidth: 1,
-  fill: '#ffffff',
   stroke: '#000000',
   fontSize: 16,
   align: "center",
@@ -23,11 +22,11 @@ export const defaultStyle = {
 
 export const getMouseStyle = (data: RectangleData) => {
   const fillStatus = data.fill && getMouseColors(data.fill);
-  const strokeStatus = getMouseColors(data.stroke || themeColor);
+  const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
   const strokeWidth = data.strokeWidth || defaultStyle.strokeWidth;
 
   return {
-    default: { fill: data.fill || defaultStyle.fill, stroke: data.stroke || defaultStyle.stroke, strokeWidth },
+    default: { fill: data.fill , stroke: data.stroke || defaultStyle.stroke, strokeWidth },
     hover: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus.hover },
     focus: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus.hover },
     press: { fill: fillStatus && fillStatus.press, stroke: strokeStatus.press },
@@ -109,4 +108,9 @@ export const matResponse = ({data, mat, increment}: MatResponseProps<'rectangle'
   data.points = data.points.map((v) => transfrom.point(v));
   data.attitude = transfrom.copy().multiply(attitude).m;
   return data;
+}
+export const getPredefine = (key: keyof RectangleData) => {
+  if (key === 'fill') {
+    return { canun: true }
+  }
 }

+ 2 - 1
src/core/components/rectangle/rectangle.vue

@@ -10,6 +10,7 @@
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate :target="shape" :menus="operateMenus" />
 </template>
@@ -52,7 +53,7 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus({
     "fontSize",
     // "ref",
     "opacity",
-    "dash",
+    // "dash",
     //  "zIndex"
     "align",
     "fontStyle",

+ 5 - 0
src/core/components/serial/index.ts

@@ -92,4 +92,9 @@ export const matResponse = ({data, mat, increment}: MatResponseProps<'serial'>,
     .translate(dec.x, dec.y)
     .rotate(0).m;
   return data;
+}
+export const getPredefine = (key: keyof CircleData) => {
+  if (key === 'fill') {
+    return { canun: true }
+  }
 }

+ 2 - 1
src/core/components/serial/serial.vue

@@ -10,6 +10,7 @@
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate :target="shape" :menus="operateMenus" />
 </template>
@@ -84,7 +85,7 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus<
     // "fontSize",
     // "ref",
     "opacity",
-    "dash",
+    // "dash",
     //  "zIndex"
     "fontStyle",
     // "ref", "zIndex"

+ 6 - 4
src/core/components/share/text-area.vue

@@ -107,10 +107,12 @@ const show = ref(false);
 watch(
   () => props.shape,
   (shape) => {
-    shape.on("dblclick", () => {
-      text.value = props.content || props.shape.text();
-      show.value = true;
-      emit("show");
+    shape.on("dblclick", (ev) => {
+      if (ev.evt.button === 0) {
+        text.value = props.content || props.shape.text();
+        show.value = true;
+        emit("show");
+      }
     });
   },
   { immediate: true }

+ 3 - 1
src/core/components/share/text.vue

@@ -1,7 +1,7 @@
 <template>
   <v-text :config="{ ...config, text }" ref="shape" name="text" />
   <TextDom
-    v-if="shape && editer"
+    v-if="shape && editer && can.editMode"
     :content="props.config.text"
     :shape="shape.getNode()"
     @submit="submitHandler"
@@ -16,6 +16,7 @@ import { DC } from "@/deconstruction";
 import { Text, TextConfig } from "konva/lib/shapes/Text";
 import { computed, ref } from "vue";
 import TextDom from "./text-area.vue";
+import { useCan, useMode } from "@/core/hook/use-status";
 
 const props = withDefaults(
   defineProps<{
@@ -32,6 +33,7 @@ const emit = defineEmits<{
   (e: "update:isEdit", val: boolean): void;
 }>();
 const shape = ref<DC<Text>>();
+const can = useCan();
 const editText = ref(false);
 const shapesStatus = useMouseShapesStatus();
 const text = computed(() => {

+ 8 - 1
src/core/components/table/index.ts

@@ -44,6 +44,7 @@ export type TableCollData = Partial<typeof defaultCollData> &
 export type TableData = Partial<typeof defaultStyle> &
   BaseItem &
   Size & {
+    fill?: string
     notaddRow?: boolean;
     notaddCol?: boolean;
     mat: number[];
@@ -51,7 +52,7 @@ export type TableData = Partial<typeof defaultStyle> &
   };
 
 export const getMouseStyle = (data: TableData) => {
-  const strokeStatus = getMouseColors(data.stroke || themeColor);
+  const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
 
   return {
     default: { stroke: data.stroke || defaultStyle.stroke },
@@ -201,3 +202,9 @@ export const matResponse = (
   }
   return data;
 };
+
+export const getPredefine = (key: keyof TableData) => {
+  if (key === 'fill') {
+    return { canun: true }
+  }
+}

+ 6 - 53
src/core/components/table/table.vue

@@ -11,6 +11,7 @@
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate
     :target="shape"
@@ -36,12 +37,12 @@ import { MathUtils } from "three";
 import {
   useCustomTransformer,
   useGetTransformerOperType,
+  useTransformer,
 } from "@/core/hook/use-transformer.ts";
 import { copy, getResizeCorsur } from "@/utils/shared.ts";
 import { computed, ref, watch, watchEffect } from "vue";
 import { Group } from "konva/lib/Group";
 import { DC } from "@/deconstruction.js";
-import { Minus, Plus } from "@element-plus/icons-vue";
 import { Rect } from "konva/lib/shapes/Rect";
 import { setShapeTransform } from "@/utils/shape.ts";
 import { Text } from "konva/lib/shapes/Text";
@@ -50,7 +51,7 @@ import {
   useMouseShapeStatus,
 } from "@/core/hook/use-mouse-status.ts";
 import { useCursor, usePointerPos } from "@/core/hook/use-global-vars.ts";
-import { numEq, Pos } from "@/utils/math.ts";
+import { Pos } from "@/utils/math.ts";
 
 const props = defineProps<{ data: TableData }>();
 const emit = defineEmits<{
@@ -117,9 +118,6 @@ watch(
       onCleanup(() => {
         inter = null;
         pop();
-        // if (isActive) {
-        //   shapesStatus.actives = [...shapesStatus.actives, $shape];
-        // }
       });
     }
   },
@@ -139,50 +137,7 @@ const matToData = (data: TableData, mat: Transform, initData?: TableData) => {
   }
   const dec = mat.decompose();
   if (!inter || (!~inter.colBorderNdx && !~inter.rowBorderNdx)) {
-    const oldData = copy(data);
-    data.height = dec.scaleY * initData.height;
-    data.width = dec.scaleX * initData.width;
-
-    let w = 0;
-    let h = 0;
-    data.content.forEach((row, rndx) => {
-      row.forEach((col, cndx) => {
-        const initCol = initData.content[rndx][cndx];
-        const minSize = getColMinSize(initCol);
-        col.width = Math.max(minSize.w, data.width * (initCol.width / initData.width));
-        col.height = Math.max(
-          minSize.h,
-          data.height * (initCol.height / initData.height)
-        );
-        if (rndx === 0) {
-          w += col.width;
-        }
-        if (cndx === 0) {
-          h += col.height;
-        }
-      });
-    });
-    const eqW = numEq(w, data.width);
-    const eqH = numEq(h, data.height);
-
-    if (!eqW || !eqH) {
-      const type = getOperType();
-      if (type) {
-        Object.assign(data, oldData);
-      } else {
-        data.width = w;
-        data.height = h;
-        const initDec = new Transform(initData.mat).decompose();
-        data.mat = new Transform()
-          .translate(eqW ? dec.x : initDec.x, eqH ? dec.y : initDec.y)
-          .rotate(MathUtils.degToRad(dec.rotation)).m;
-      }
-    } else {
-      data.mat = new Transform()
-        .translate(dec.x, dec.y)
-        .rotate(MathUtils.degToRad(dec.rotation)).m;
-    }
-    return data;
+    return matResponse({ data, mat, operType: getOperType()! }, initData);
   }
 
   const initDec = new Transform(initData.mat).decompose();
@@ -235,6 +190,7 @@ const matToData = (data: TableData, mat: Transform, initData?: TableData) => {
 };
 
 let repShape: Rect | null;
+const transformer = useTransformer();
 const sync = (data: TableData) => {
   if (repShape) {
     repShape.width(data.width);
@@ -242,6 +198,7 @@ const sync = (data: TableData) => {
     const tf = new Transform(data.mat);
     setShapeTransform(repShape, tf);
     initData = copy(data);
+    transformer.forceUpdate();
   }
 };
 
@@ -342,7 +299,6 @@ const menuShowHandler = () => {
   addMenu = [];
   if (!data.value.notaddRow) {
     addMenu.push({
-      icon: Plus,
       label: "插入行",
       handler: () => {
         const temprow = data.value.content[config.rowNdx];
@@ -360,7 +316,6 @@ const menuShowHandler = () => {
   const canDelRaw = data.value.content[config.rowNdx].every((item) => !item.notdel);
   if (canDelRaw) {
     addMenu.push({
-      icon: Minus,
       label: "删除行",
       handler: () => {
         const temprow = data.value.content[config.rowNdx];
@@ -378,7 +333,6 @@ const menuShowHandler = () => {
 
   if (!data.value.notaddCol) {
     addMenu.push({
-      icon: Plus,
       label: "插入列",
       handler: () => {
         const tempCol = data.value.content[0][config.colNdx];
@@ -396,7 +350,6 @@ const menuShowHandler = () => {
   const canDelCol = data.value.content.every((items) => !items[config.colNdx].notdel);
   if (canDelCol) {
     addMenu.push({
-      icon: Minus,
       label: "删除列",
       handler: () => {
         const tempCol = data.value.content[0][config.colNdx];

+ 8 - 2
src/core/components/text/index.ts

@@ -1,6 +1,5 @@
 import { Transform } from "konva/lib/Util";
 import { Text } from "konva/lib/shapes/Text";
-import { themeColor } from "@/constant/help-style.ts";
 import {
   BaseItem,
   generateSnapInfos,
@@ -31,6 +30,7 @@ export const addMode = "dot";
 
 export type TextData = Partial<typeof defaultStyle> &
   BaseItem & {
+    stroke?: string
     mat: number[];
     content: string;
     width?: number;
@@ -38,7 +38,7 @@ export type TextData = Partial<typeof defaultStyle> &
   };
 
 export const getMouseStyle = (data: TextData) => {
-  const fillStatus = getMouseColors(data.fill || themeColor);
+    const fillStatus = getMouseColors(data.fill || defaultStyle.fill);
   // const strokeStatus = getMouseColors(data.stroke || defaultStyle.stroke);
   // const strokeWidth = data.strokeWidth || defaultStyle.strokeWidth;
 
@@ -119,3 +119,9 @@ export const matResponse = ({ data, mat, increment }: MatResponseProps<"text">)
   }
   return data
 };
+
+export const getPredefine = (key: keyof TextData) => {
+  if (key === 'stroke') {
+    return { canun: true }
+  }
+}

+ 10 - 5
src/core/components/text/text.vue

@@ -10,6 +10,7 @@
     :data="data"
     :target="shape"
     @change="emit('updateShape', { ...data })"
+    @delete="emit('delShape')"
   />
   <Operate :target="shape" :menus="operateMenus" />
 </template>
@@ -50,16 +51,19 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus<
   defaultStyle,
   transformType: "custom",
   customTransform(callback, shape, data) {
+    let initData: TextData;
     useCustomTransformer(shape, data, {
       openSnap: true,
       getRepShape($shape) {
         const repShape = cloneRepShape($shape).shape;
         setShapeTransform(repShape, new Transform(data.value.mat));
+        repShape.width(data.value.width);
+        repShape.fontSize(data.value.fontSize);
+        initData = copy(data.value);
         return {
           shape: repShape,
           update(data) {
-            data.width && repShape.width(data.width);
-            data.fontSize && repShape.fontSize(data.fontSize);
+            console.log("update");
           },
         };
       },
@@ -74,11 +78,12 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus<
         },
       },
       beforeHandler(data, mat) {
-        return matResponse({ data: copy(data), mat });
+        return matResponse({ mat, data: copy(initData) });
       },
       handler(data, mat) {
-        const a = matResponse({ mat, data });
+        const a = matResponse({ mat, data: copy(initData) });
         if (a.width) {
+          Object.assign(data, a);
           return true;
         }
       },
@@ -95,7 +100,7 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus<
     "fill",
     "stroke",
     "strokeWidth",
-    "dash",
+    // "dash",
     "opacity",
     "fontSize",
     "align",

+ 9 - 5
src/core/components/triangle/index.ts

@@ -1,5 +1,4 @@
 import { Pos } from "@/utils/math.ts";
-import { themeMouseColors } from "@/constant/help-style.ts";
 import { BaseItem, generateSnapInfos, getBaseItem } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
 import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts";
@@ -10,13 +9,12 @@ export { default as TempComponent } from "./temp-triangle.vue";
 
 export const shapeName = "三角形";
 export const defaultStyle = {
-  stroke: themeMouseColors.theme,
+  stroke: '#000000',
   strokeWidth: 5,
   fontSize: 16,
   align: "center",
-  fill: '#ffffff',
   fontStyle: "normal",
-  fontColor: themeMouseColors.theme,
+  fontColor: '#000000',
 };
 
 export const addMode = "area";
@@ -28,7 +26,7 @@ export const getMouseStyle = (data: TriangleData) => {
 
   return {
     default: {
-      fill: data.fill || defaultStyle.fill,
+      fill: data.fill,
       stroke: data.stroke || defaultStyle.stroke,
       strokeWidth,
     },
@@ -98,4 +96,10 @@ export const matResponse = ({data, mat, increment}: MatResponseProps<'triangle'>
   data.points = data.points.map((v) => transfrom.point(v));
   data.attitude = transfrom.copy().multiply(attitude).m;
   return data;
+}
+
+export const getPredefine = (key: keyof TriangleData) => {
+  if (key === 'fill') {
+    return { canun: true }
+  }
 }

+ 2 - 1
src/core/components/triangle/triangle.vue

@@ -10,6 +10,7 @@
     :describes="describes"
     :data="data"
     :target="shape"
+    @delete="emit('delShape')"
     @change="emit('updateShape', { ...data })"
   />
   <Operate :target="shape" :menus="operateMenus" />
@@ -52,7 +53,7 @@ const { shape, tData, operateMenus, describes, data } = useComponentStatus({
     "fontSize",
     // "ref",
     "opacity",
-    "dash",
+    // "dash",
     //  "zIndex"
     "align",
     "fontStyle",

+ 3 - 1
src/core/components/util.ts

@@ -13,6 +13,7 @@ export type BaseItem = {
   key?: string
   layer: string
   ref: boolean
+  hide?: boolean
   listening?: boolean
 };
 
@@ -23,7 +24,8 @@ export const getBaseItem = (): BaseItem => ({
   zIndex: 0,
   layer: defaultLayer,
   opacity: 1,
-  ref: false
+  ref: false,
+  hide: false
 });
 
 export const getRectSnapPoints = (

+ 0 - 4
src/core/helper/layers.vue

@@ -86,9 +86,5 @@ const store = useStore();
       color: var(--el-color-primary);
     }
   }
-  .el-menu-item [class^="el-icon"] {
-    margin: 0;
-    font-size: 1em;
-  }
 }
 </style>

+ 11 - 17
src/core/hook/use-component.ts

@@ -22,17 +22,6 @@ import {
 import { components, DrawItem, ShapeType } from "../components";
 import { useMatCompTransformer, useLineTransformer } from "./use-transformer";
 import { useGetShapeCopyTransform } from "./use-copy";
-import {
-  Bottom,
-  Delete,
-  DocumentCopy,
-  Download,
-  Location,
-  Lock,
-  Top,
-  Unlock,
-  Upload,
-} from "@element-plus/icons-vue";
 import { asyncTimeout, copy, mergeFuns, onlyId } from "@/utils/shared";
 import { Shape } from "konva/lib/Shape";
 import { Transform } from "konva/lib/Util";
@@ -83,7 +72,6 @@ export const useComponentMenus = <T extends DrawItem>(
     // },
     {
       label: `置顶`,
-      icon: Upload,
       handler() {
         data.value.zIndex = currentZIndex.max + 1;
         emit("updateShape", { ...data.value });
@@ -91,7 +79,6 @@ export const useComponentMenus = <T extends DrawItem>(
     },
     {
       label: `置底`,
-      icon: Download,
       handler() {
         data.value.zIndex = currentZIndex.min - 1;
         emit("updateShape", { ...data.value });
@@ -103,7 +90,6 @@ export const useComponentMenus = <T extends DrawItem>(
   operateMenus.push(
     reactive({
       label: computed(() => (data.value.lock ? "解锁" : "锁定")) as any,
-      icon: computed(() => (data.value.lock ? Unlock : Lock)),
       handler() {
         data.value.lock = !data.value.lock;
         emit("updateShape", { ...data.value });
@@ -123,17 +109,26 @@ export const useComponentMenus = <T extends DrawItem>(
         // emit('addShape', ndata)
         // emit('delShape')
       },
-      icon: Location,
     });
   }
 
+  // 隐藏
+  operateMenus.push(
+    reactive({
+      label: '隐藏',
+      handler() {
+        data.value.hide = true;
+        emit("updateShape", { ...data.value });
+      },
+    })
+  );
+
   if (copyHandler) {
     const getCopyTransform = useGetShapeCopyTransform(shape);
     const status = useMouseShapesStatus();
     const stage = useStage();
     operateMenus.push({
       label: `复制`,
-      icon: DocumentCopy,
       async handler() {
         const transform = getCopyTransform();
         const copyData = copyHandler(
@@ -156,7 +151,6 @@ export const useComponentMenus = <T extends DrawItem>(
 
   operateMenus.push({
     label: `删除`,
-    icon: Delete,
     handler() {
       emit("delShape");
     },

+ 4 - 7
src/core/hook/use-draw.ts

@@ -10,7 +10,7 @@ import {
   useInteractiveProps,
 } from "./use-interactive";
 import { Mode } from "@/constant/mode";
-import { copy, debounce, mergeFuns } from "@/utils/shared";
+import { copy, mergeFuns } from "@/utils/shared";
 import {
   Components,
   components,
@@ -27,8 +27,6 @@ import { generateSnapInfos } from "../components/util";
 import { useStore, useStoreRenderProcessors } from "../store";
 import DrawShape from "../renderer/draw-shape.vue";
 import { useHistory, useHistoryAttach } from "./use-history";
-import penA from "../assert/cursor/pic_pen_a.ico";
-import penR from "../assert/cursor/pic_pen_r.ico";
 import { useCurrentZIndex } from "./use-layer";
 import { useViewerTransform } from "./use-viewer";
 
@@ -75,7 +73,6 @@ export const useInteractiveDrawShapeAPI = installGlobalVar(() => {
   return {
     delShape(id: string) {
       const type = store.getType(id);
-      console.log(type, id);
       type && store.delItem(type, id);
     },
     addShape: <T extends ShapeType>(
@@ -84,7 +81,6 @@ export const useInteractiveDrawShapeAPI = installGlobalVar(() => {
       data?: PayData<T>,
       pixel = false
     ) => {
-      console.log(can.dragMode);
       if (!can.drawMode) {
         throw "当前状态不允许添加";
       }
@@ -133,6 +129,7 @@ export const useInteractiveDrawShapeAPI = installGlobalVar(() => {
       leave();
       interactiveProps.value = void 0;
     },
+    drawing: computed(() => mode.include(Mode.draw))
   };
 });
 
@@ -499,7 +496,7 @@ export const useInteractiveDrawPen = <T extends ShapeType>(type: T) => {
 
   const getAddMessage = (cur: Pos) => {
     let consumed = messages.value;
-    currentCursor.value = penA;
+    currentCursor.value = '/icons/m_add.png';
     let pen: null | ReturnType<typeof penUpdatePoints> = null;
     if (!operMode.value.freeDraw) {
       // pen = penUpdatePoints(messages.value, cur, type !== "polygon");
@@ -518,7 +515,7 @@ export const useInteractiveDrawPen = <T extends ShapeType>(type: T) => {
   const setMessage = (cur: Pos) => {
     const { pen, ...msg } = getAddMessage(cur);
     if ((currentIsDel = pen?.oper === "del")) {
-      currentCursor.value = penR;
+      currentCursor.value = '/icons/m_reduce.png';
       beforeHandler.clear();
     }
     return msg;

+ 14 - 5
src/core/hook/use-expose.ts

@@ -21,7 +21,7 @@ import { Mode } from "@/constant/mode.ts";
 import { ElMessageBox } from "element-plus";
 import { mergeFuns } from "@/utils/shared.ts";
 import { themeColor } from "@/constant/help-style.ts";
-import { isSvgString } from "@/utils/resource.ts";
+import { getImage, isSvgString } from "@/utils/resource.ts";
 import { useResourceHandler } from "./use-fetch.ts";
 import { useConfig } from "./use-config.ts";
 import { useSelectionRevise } from "./use-selection.ts";
@@ -53,7 +53,15 @@ export const useAutoPaste = () => {
         if (type.includes("svg")) {
           drawAPI.addShape("icon", { url, stroke: themeColor }, pos, true);
         } else {
-          drawAPI.addShape("image", { url }, pos, true);
+          const image = await getImage(url);
+          drawAPI.addShape(
+            "image",
+            { url, 
+              // width: image.width, height: image.height 
+            },
+            pos,
+            true
+          );
         }
       },
       type: "file",
@@ -223,14 +231,16 @@ export const useExpose = installGlobalVar(() => {
 
   const formalLayer = useFormalLayer();
   const initViewport = () => {
-    const rect = formalLayer.value!.findOne<Group>('#' + DataGroupId)!.getClientRect();
+    const rect = formalLayer
+      .value!.findOne<Group>("#" + DataGroupId)!
+      .getClientRect();
     const invMat = viewer.transform.invert();
     const lt = invMat.point(rect);
     const rb = invMat.point({
       x: rect.x + rect.width,
       y: rect.y + rect.height,
     });
-    console.log()
+    console.log();
     viewer.setBound({
       targetBound: {
         ...lt,
@@ -240,7 +250,6 @@ export const useExpose = installGlobalVar(() => {
       padding: 20,
     });
   };
-  
 
   return {
     ...useInteractiveDrawShapeAPI(),

+ 0 - 1
src/core/hook/use-paste.ts

@@ -38,7 +38,6 @@ export const usePaste = installGlobalVar(() => {
   return {
     var: handlers,
     onDestroy: () => {
-      console.log('取消监听')
       stop()
     }
   };

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

@@ -472,7 +472,7 @@ export const cloneRepShape = <T extends EntityShape>(
     shape;
   return {
     shape: shape.clone({
-      fill: "rgb(0, 255, 0)",
+      fill: themeColor,
       visible: false,
       strokeWidth: 0,
     }),

+ 53 - 0
src/core/html-mount/propertys/components/color-free.vue

@@ -0,0 +1,53 @@
+<template>
+  <el-color-picker
+    :modelValue="value"
+    @active-change="inputHandler"
+    @update:model-value="inputHandler"
+    popper-class="com-color-pick"
+    size="small"
+    :predefine="predefineColors"
+    @blur="changeHandler"
+  />
+</template>
+
+<script lang="ts" setup>
+import { ref } from "vue";
+import { ElColorPicker } from "element-plus";
+
+defineProps<{ value?: string }>();
+
+const emit = defineEmits<{
+  (e: "update:value", val: string | null): string;
+  (e: "change"): void;
+}>();
+
+let change = false;
+const inputHandler = (color: string | null) => {
+  emit("update:value", color);
+  change = true;
+};
+
+const changeHandler = () => {
+  if (change) {
+    emit("change");
+    change = false;
+  }
+};
+
+const predefineColors = ref([
+  "#ff4500",
+  "#ff8c00",
+  "#ffd700",
+  "#90ee90",
+  "#00ced1",
+  "#1e90ff",
+  "#c71585",
+  "rgba(255, 69, 0, 0.68)",
+  "rgb(255, 120, 0)",
+  "hsv(51, 100, 98)",
+  "hsva(120, 40, 94, 0.5)",
+  "hsl(181, 100%, 37%)",
+  "hsla(209, 100%, 56%, 0.73)",
+  "#c7158577",
+]);
+</script>

+ 69 - 39
src/core/html-mount/propertys/components/color.vue

@@ -1,53 +1,83 @@
 <template>
-  <el-color-picker
-    :modelValue="value"
-    @active-change="inputHandler"
-    @update:model-value="inputHandler"
-    popper-class="com-color-pick"
-    size="small"
-    :predefine="predefineColors"
-    @blur="changeHandler"
-  />
+  <div class="color-layout">
+    <span
+      v-for="color in predefineColors"
+      :style="color && { backgroundColor: color }"
+      :class="{
+        weight: color === '#FFFFFF' || color === null,
+        tran: color === null,
+        active: (value && value.toUpperCase() === color) || (!value && !color),
+      }"
+      @click="
+        () => {
+          emit('update:value', color);
+          emit('change');
+        }
+      "
+    />
+  </div>
 </template>
 
 <script lang="ts" setup>
 import { ref } from "vue";
-import { ElColorPicker } from "element-plus";
+import { themeColor } from "@/constant/help-style";
 
-defineProps<{ value?: string }>();
+const props = defineProps<{ value?: string; canun?: boolean }>();
 
 const emit = defineEmits<{
   (e: "update:value", val: string | null): string;
   (e: "change"): void;
 }>();
 
-let change = false;
-const inputHandler = (color: string | null) => {
-  emit("update:value", color);
-  change = true;
-};
-
-const changeHandler = () => {
-  if (change) {
-    emit("change");
-    change = false;
-  }
-};
-
-const predefineColors = ref([
-  "#ff4500",
-  "#ff8c00",
-  "#ffd700",
-  "#90ee90",
-  "#00ced1",
-  "#1e90ff",
-  "#c71585",
-  "rgba(255, 69, 0, 0.68)",
-  "rgb(255, 120, 0)",
-  "hsv(51, 100, 98)",
-  "hsva(120, 40, 94, 0.5)",
-  "hsl(181, 100%, 37%)",
-  "hsla(209, 100%, 56%, 0.73)",
-  "#c7158577",
+const predefineColors = ref<Array<string | null>>([
+  "#000000",
+  "#FFFFFF",
+  "#DD2C2C",
+  "#FF8800",
+  "#FFBE00",
+  "#1AAD19",
+  themeColor,
 ]);
+if (props.canun) {
+  predefineColors.value.push(null);
+}
 </script>
+
+<style lang="scss" scoped>
+.color-layout {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+
+  span {
+    cursor: pointer;
+    width: 24px;
+    height: 24px;
+    border-radius: 4px;
+
+    &.weight {
+      border: 1px solid #ccc;
+    }
+
+    &.tran {
+      background: #fff;
+      overflow: hidden;
+      position: relative;
+
+      &::after {
+        content: "";
+        position: absolute;
+        width: 30px;
+        height: 2px;
+        transform: rotate(45deg) translate(3px, 10px);
+        background-color: var(--el-color-danger);
+      }
+    }
+
+    &.active {
+      outline: 2px solid var(--el-color-primary);
+      outline-offset: 2px;
+    }
+  }
+}
+</style>

+ 11 - 1
src/core/html-mount/propertys/components/num.vue

@@ -35,11 +35,21 @@ const changeHandler = (val: number) => {
 
 <style lang="scss">
 .property-num-slider {
+  --el-slider-height: 4px;
+  --el-slider-button-size: 14px;
+  .el-slider__button {
+    margin-top: -2px;
+  }
   .el-input__wrapper {
     padding: 0 !important;
   }
   .el-slider__input {
-    width: 50px;
+    width: 98px;
+    height: 32px;
+  }
+  .el-input__inner {
+    text-align: left;
+    padding: 0 8px;
   }
   .el-input-number__increase,
   .el-input-number__decrease {

+ 11 - 2
src/core/html-mount/propertys/components/proportion.vue

@@ -42,14 +42,23 @@ const changeHandler = (val: number) => {
   emit("update:value", [val, props.scale - val]);
 };
 </script>
-
 <style lang="scss">
 .property-proportion-slider {
+  --el-slider-height: 4px;
+  --el-slider-button-size: 14px;
+  .el-slider__button {
+    margin-top: -2px;
+  }
   .el-input__wrapper {
     padding: 0 !important;
   }
   .el-slider__input {
-    width: 50px;
+    width: 98px;
+    height: 32px;
+  }
+  .el-input__inner {
+    text-align: left;
+    padding: 0 8px;
   }
   .el-input-number__increase,
   .el-input-number__decrease {

+ 1 - 2
src/core/html-mount/propertys/components/select.vue

@@ -3,9 +3,8 @@
     :model-value="value"
     @update:model-value="(value) => $emit('update:value', value)"
     placeholder="选择"
-    size="small"
     @change="$emit('change')"
-    style="width: 100px"
+    style="width: 98px"
   >
     <el-option
       v-for="item in options"

+ 39 - 20
src/core/html-mount/propertys/describes.json

@@ -1,42 +1,50 @@
 {
   "stroke": {
     "type": "color",
-    "label": "边框色"
+    "label": "边框色",
+    "layout-type": "column"
   },
   "coverStroke": {
     "type": "color",
-    "label": "背景边框颜色"
+    "label": "背景边框颜色",
+    "layout-type": "column"
   },
   "fill": {
     "type": "color",
-    "label": "填充色"
+    "label": "填充色",
+    "layout-type": "column"
   },
   "fontColor": {
     "type": "color",
-    "label": "字体颜色"
+    "label": "字体颜色",
+    "layout-type": "column"
   },
   "coverFill": {
     "type": "color",
-    "label": "背景颜色"
+    "label": "背景颜色",
+    "layout-type": "column"
   },
   "ref": {
     "type": "check",
     "label": "参考物",
-    "default": false
+    "default": false,
+    "layout-type": "row"
   },
   "strokeScaleEnabled": {
     "type": "check",
     "label": "固定边框粗细",
-    "default": false
+    "default": false,
+    "layout-type": "row"
   },
   "strokeWidth": {
     "type": "num",
     "label": "边框粗细",
     "default": 1,
     "props": {
-      "min": 0,
+      "min": 0.1,
       "max": 10
-    }
+    },
+    "layout-type": "column"
   },
   "rotate": {
     "type": "num",
@@ -45,7 +53,8 @@
     "props": {
       "min": -180,
       "max": 180
-    }
+    },
+    "layout-type": "column"
   },
   "coverStrokeWidth": {
     "type": "num",
@@ -54,7 +63,8 @@
     "props": {
       "min": 0.5,
       "max": 10
-    }
+    },
+    "layout-type": "column"
   },
   "opacity": {
     "type": "num",
@@ -64,7 +74,8 @@
       "max": 1,
       "step": 0.01
     },
-    "default": 1
+    "default": 1,
+    "layout-type": "column"
   },
   "coverOpcatiy": {
     "type": "num",
@@ -74,7 +85,8 @@
       "max": 1,
       "step": 0.01
     },
-    "default": 1
+    "default": 1,
+    "layout-type": "column"
   },
   "zIndex": {
     "type": "num",
@@ -84,7 +96,8 @@
       "max": 1000,
       "step": 1
     },
-    "default": 0
+    "default": 0,
+    "layout-type": "column"
   },
   "pointerLength": {
     "type": "num",
@@ -92,7 +105,8 @@
     "props": {
       "min": 0.5,
       "max": 10
-    }
+    },
+    "layout-type": "column"
   },
   "align": {
     "type": "select",
@@ -112,7 +126,8 @@
           "value": "right"
         }
       ]
-    }
+    },
+    "layout-type": "row"
   },
   "fontSize": {
     "type": "num",
@@ -120,7 +135,8 @@
     "props": {
       "min": 12,
       "max": 100
-    }
+    },
+    "layout-type": "column"
   },
   "fontStyle": {
     "type": "select",
@@ -144,7 +160,8 @@
           "value": "italic bold"
         }
       ]
-    }
+    },
+    "layout-type": "row"
   },
   "dash": {
     "type": "proportion",
@@ -155,7 +172,8 @@
     "default": [
       1,
       0
-    ]
+    ],
+    "layout-type": "column"
   },
   "pointerPosition": {
     "type": "select",
@@ -175,6 +193,7 @@
           "value": "all"
         }
       ]
-    }
+    },
+    "layout-type": "row"
   }
 }

+ 10 - 13
src/core/html-mount/propertys/hover-operate.vue

@@ -8,16 +8,9 @@
         class="propertys-controller"
         ref="layout"
       >
-        <!-- <div class="item" v-for="menu in menus" @click="menu.handler">
-          <ElButton type="primary" link :icon="menu.icon">
-            {{ menu.label }}
-          </ElButton>
-        </div> -->
-
         <ElMenu>
           <ElMenuItem v-for="menu in menus" @click="clickHandler(menu.handler)">
-            <el-icon><component :is="menu.icon" /></el-icon>
-            <span>{{ menu.label }}</span>
+            <span class="menu-item">{{ menu.label }}</span>
           </ElMenuItem>
         </ElMenu>
       </div>
@@ -33,7 +26,7 @@ import { DC, EntityShape } from "@/deconstruction.js";
 import { useViewerTransformConfig } from "../../hook/use-viewer.ts";
 import { Transform } from "konva/lib/Util";
 import { DomMountId } from "@/constant/index.ts";
-import { ElMenu, ElIcon, ElMenuItem } from "element-plus";
+import { ElMenu, ElMenuItem } from "element-plus";
 import { useFormalLayer } from "../../hook/use-layer.ts";
 import { shapeTreeContain } from "@/utils/shape.ts";
 import { Mode } from "@/constant/mode.ts";
@@ -178,6 +171,14 @@ watch(useViewerTransformConfig(), () => {
 // watch(() => props.data, resetPointer);
 </script>
 
+<style lang="scss" scoped>
+.menu-item {
+  display: block;
+  min-width: 60px;
+  margin-left: 10px;
+}
+</style>
+
 <style lang="scss">
 .propertys-controller {
   pointer-events: none;
@@ -210,10 +211,6 @@ watch(useViewerTransformConfig(), () => {
     padding: 5px 16px 5px 6px !important;
     color: var(--el-text-color-regular);
   }
-  .el-menu-item [class^="el-icon"] {
-    margin: 0;
-    font-size: 1em;
-  }
 }
 
 .pointer-fade-enter-active,

+ 1 - 0
src/core/html-mount/propertys/index.ts

@@ -35,6 +35,7 @@ export type PropertyDescribes = Record<
     type: PropertyType;
     label: string;
     default?: PropertyValue<PropertyType>;
+    'layout-type'?: string;
     props?: Partial<PropertyProps<PropertyType>>;
     value?: PropertyValue<PropertyType>;
     sort?: number

+ 87 - 27
src/core/html-mount/propertys/mount.vue

@@ -2,11 +2,25 @@
   <Teleport :to="`#${DomOutMountId}`" v-if="stage">
     <transition name="mount-fade">
       <div class="mount-layout" v-if="show">
+        <div v-if="type && components[type].shapeName" class="title">
+          <h4>设置{{ components[type].shapeName }}</h4>
+          <icon
+            name="close"
+            size="20px"
+            class="operate"
+            @click="shapesStatus.actives = []"
+          />
+        </div>
         <div :size="8" class="mount-controller">
-          <div v-for="[key, val] in describeItems" :key="key" class="mount-item">
+          <div
+            v-for="[key, val] in describeItems"
+            :key="key"
+            class="mount-item"
+            :class="val['layout-type'] || 'column'"
+          >
             <span class="label">{{ val.label }}</span>
             <component
-              v-bind="describes[key].props"
+              v-bind="{ ...describes[key].props, ...getPredefine(key) }"
               :value="
                 'value' in describes[key] ? describes[key].value : data && data[key]
               "
@@ -17,21 +31,32 @@
             />
           </div>
         </div>
+        <div class="mount-bottom">
+          <el-button type="danger" plain @click="emit('delete')" class="del-btn">
+            删除
+          </el-button>
+        </div>
       </div>
     </transition>
   </Teleport>
 </template>
 
 <script lang="ts" setup>
-import { computed, ref, watch } from "vue";
+import { computed, ref, watch, watchEffect } from "vue";
 import { useStage } from "../../hook/use-global-vars.ts";
 import { useMode } from "../../hook/use-status.ts";
 import { PropertyDescribes, propertyComponents } from "./index.ts";
 import { DC, EntityShape } from "@/deconstruction.js";
-import { useMouseShapeStatus } from "../../hook/use-mouse-status.ts";
+import {
+  useMouseShapesStatus,
+  useMouseShapeStatus,
+} from "../../hook/use-mouse-status.ts";
 import { DomOutMountId } from "@/constant/index.ts";
 import { Mode } from "@/constant/mode.ts";
 import { debounce } from "@/utils/shared.ts";
+import { useStore } from "@/core/store/index.ts";
+import { components, DrawItem } from "@/core/components/index.ts";
+import { ElButton } from "element-plus";
 
 const props = defineProps<{
   show?: boolean;
@@ -39,8 +64,25 @@ const props = defineProps<{
   data?: Record<string, any>;
   describes: PropertyDescribes;
 }>();
-const emit = defineEmits<{ (e: "change"): void }>();
+const emit = defineEmits<{
+  (e: "change"): void;
+  (e: "delete"): void;
+  (e: "close"): void;
+}>();
 
+const store = useStore();
+const type = computed(() => {
+  const id = props.target?.getNode().id();
+  if (!id) return;
+  return store.getType(id);
+});
+
+const getPredefine = (key: string) => {
+  if (!type.value) return;
+  const getPredefine = components[type.value].getPredefine;
+  const predefine = getPredefine && (getPredefine as any)(key as keyof DrawItem);
+  return predefine || {};
+};
 const describeItems = computed(() => {
   return Object.entries(props.describes).sort(
     ([_a, a], [_b, b]) => (b.sort || -1) - (a.sort || -1)
@@ -49,6 +91,7 @@ const describeItems = computed(() => {
 
 const stage = useStage();
 const status = useMouseShapeStatus(computed(() => props.target));
+const shapesStatus = useMouseShapesStatus();
 const mode = useMode();
 const hidden = computed(
   () =>
@@ -97,40 +140,50 @@ const changeHandler = () => {
   top: 0;
   bottom: 0;
   position: absolute;
-  border-left: 1px solid #e4e7ed;
-  background-color: rgba(255, 255, 255, 0.7);
+  border-left: 1px solid #e6e6e6;
+  background-color: rgba(255, 255, 255, 1);
   overflow-y: auto;
-  padding: 6px 12px;
-  color: #303133;
-  width: 240px;
-  font-size: 12px;
+  padding: 6px 16px;
+  color: #333333;
+  width: 280px;
+  font-size: 14px;
   box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
   overflow: hidden;
 
   .mount-controller {
-    // display: grid;
-    // grid-template-columns: auto 1fr;
-    // gap: 10px 0;
-    // align-items: center;
-
+    border-bottom: 1px solid #f0f0f0;
+    margin-bottom: 24px;
     .mount-item {
-      margin-bottom: 15px;
-      display: flex;
-      flex-wrap: wrap;
-      align-items: center;
-    }
+      margin-bottom: 24px;
 
-    .label {
-      display: block;
-      margin-right: 10px;
-      color: #303133;
+      &.column {
+        .label {
+          display: block;
+          margin-bottom: 8px;
+        }
+      }
 
-      &::after {
-        content: ":";
+      &.row {
+        display: flex;
+        flex-wrap: wrap;
+        align-items: center;
+        justify-content: space-between;
       }
     }
   }
 }
+.title {
+  display: flex;
+  font-size: 16px;
+  padding: 19px 0 25px;
+  align-items: center;
+  justify-content: space-between;
+  h3 {
+    font-size: inherit;
+    color: #333333;
+    align-items: center;
+  }
+}
 
 .mount-fade-enter-active,
 .mount-fade-leave-active {
@@ -142,4 +195,11 @@ const changeHandler = () => {
   transform: translateX(100%);
   opacity: 0;
 }
+.del-btn {
+  width: 100%;
+  font-size: 14px;
+  height: 34px;
+  background: none;
+  color: var(--el-color-danger);
+}
 </style>

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

@@ -5,7 +5,7 @@
       @updateShape="(value: any) => store.setItem(type, { id: item.id, value })"
       @addShape="(value: any) => store.addItem(type, value)"
       @delShape="() => store.delItem(type, item.id)"
-      v-if="!itemHasRegistor(item.id)"
+      v-if="!itemHasRegistor(item.id) && !item.hide"
     />
     <template v-else>
       <component :is="renderer(item.id)" :item="item" />

+ 2 - 3
src/core/renderer/renderer.vue

@@ -11,7 +11,7 @@
       class="draw-content"
       :style="fix && { width: size?.width + 'px', height: size?.height + 'px' }"
     >
-      <div class="mount-mask" :id="DomMountId" />
+      <div class="mount-mask" :id="DomMountId"></div>
 
       <v-stage ref="stage" :config="size" v-if="layout">
         <v-layer :config="viewerConfig" id="formal">
@@ -117,7 +117,6 @@ const store = useStore();
 watch(
   () => props.data,
   (data) => {
-    console.log(data);
     store.setStore(data || getEmptyStoreData());
   },
   { immediate: true }
@@ -179,6 +178,6 @@ defineExpose(expose);
   inset: 0;
   overflow: hidden;
   pointer-events: none;
-  z-index: 999;
+  z-index: 1;
 }
 </style>

+ 1 - 2
src/core/store/store.ts

@@ -75,7 +75,6 @@ export const useStoreRaw = defineStore("draw-data", {
             ...(newStore.config || {})
           }
         };
-        console.error(state.data)
       });
     },
     setLayerStore(layerStore: DrawData) {
@@ -140,7 +139,7 @@ export const useStoreRaw = defineStore("draw-data", {
     },
     getType(id: string) {
       const typeItems = this.typeItems
-      const types = Object.keys(typeItems) as ShapeType[];
+      const types = (Object.keys(typeItems)) as ShapeType[];
       for (const type of types) {
         if (typeItems[type]?.some((item) => item.id === id)) {
           return type;

+ 28 - 2
src/example/components/container/container.vue

@@ -7,6 +7,19 @@
         <DrawBoard v-if="drawEle" :handler-resource="uploadResourse" ref="draw" />
         <slot name="cover" v-if="draw" :draw="draw" />
       </div>
+
+      <div class="confirm-items">
+        <ElButton
+          @click="draw.quitDrawShape()"
+          circle
+          class="h-bottom"
+          v-if="draw?.drawing"
+        >
+          <template #icon>
+            <icon name="pic_yes" size="32px" color="#41c732" />
+          </template>
+        </ElButton>
+      </div>
     </div>
   </div>
 </template>
@@ -15,7 +28,7 @@
 import { onUnmounted, ref, watch } from "vue";
 import { DrawBoard } from "@/index";
 import { listener } from "@/utils/event.ts";
-import { ElMessage } from "element-plus";
+import { ElMessage, ElButton } from "element-plus";
 import { mergeFuns, startAnimation } from "@/utils/shared";
 import { installDraw } from "./use-draw";
 
@@ -76,7 +89,7 @@ defineExpose({
   overflow: hidden;
 
   .container {
-    height: calc(100vh - #{global.$headerSize});
+    height: calc(100vh - #{global.$headerSize} - var(--top));
     display: flex;
     align-items: stretch;
   }
@@ -90,4 +103,17 @@ defineExpose({
     --left: calc(-1 * #{global.$slideSize});
   }
 }
+
+.confirm-items {
+  position: absolute;
+  bottom: #{global.$bottomSize};
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.h-bottom {
+  width: 64px;
+  height: 64px;
+  box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.3);
+}
 </style>

+ 17 - 1
src/example/components/header/actions.ts

@@ -3,6 +3,8 @@ import { Draw } from "../container/use-draw";
 import { animation } from "@/core/hook/use-animation";
 import saveAs from "@/utils/file-serve";
 import { ElMessage } from "element-plus";
+import { Mode } from "@/constant/mode";
+import { ShapeType } from "@/index";
 
 export type Action = {
   handler?: (draw: Draw) => void;
@@ -63,7 +65,17 @@ export const getHeaderActions = (draw: Draw) => {
       icon: "a_adapt",
     }),
     toggleShow: reactive({
-      handler: () => {},
+      handler: () => {
+        draw.history.onceTrack(() => {
+          const tItems = draw.store.typeItems
+          for (const key in tItems) {
+            const items = tItems[key as ShapeType]
+            items?.forEach(item => {
+              draw.store.setItem(key as ShapeType, {value: { hide: false }, id: item.id})
+            })
+          }
+        })
+      },
       text: "显示",
       icon: "a-visible",
     }),
@@ -77,8 +89,10 @@ export const getHeaderActions = (draw: Draw) => {
             draw.enterTemp(async () => {
               const oldShowGrid = draw.config.showGrid
               draw.config.showGrid = false
+              const pop = draw.mode.push(Mode.readonly)
               await nextTick()
               saveAs(await getImage(draw, 'image/jpeg'), "canvas.png");
+              pop()
               draw.config.showGrid = oldShowGrid
             })
           },
@@ -90,10 +104,12 @@ export const getHeaderActions = (draw: Draw) => {
             draw.enterTemp(async () => {
               const oldBack = draw.config.back && {...draw.config.back}
               const oldShowGrid = draw.config.showGrid
+              const pop = draw.mode.push(Mode.readonly)
               draw.config.showGrid = false
               draw.config.back = undefined
               await nextTick()
               await saveAs(await getImage(draw, 'image/png'), "canvas.png");
+              pop()
               draw.config.back = oldBack
               draw.config.showGrid = oldShowGrid
               ElMessage.success("导出成功");

+ 4 - 4
src/example/components/show-vr.vue

@@ -6,7 +6,7 @@
     </div>
     <div class="content" :style="{ pointerEvents: downPos ? 'none' : 'all' }">
       <iframe :src="tempStrFill(SceneTypeTempUrls[scene.type], scene)" />
-      <Icon class="full" name="close" @click="fullHandler" />
+      <Icon class="full" :name="isFull ? 'zoom_s' : 'zoom_b'" @click="fullHandler" />
     </div>
   </div>
 </template>
@@ -26,16 +26,16 @@ const vrRef = ref<HTMLDivElement>();
 const width = ref(320);
 const height = ref(220);
 
-let isFull = false;
+let isFull = ref(false);
 const fullHandler = () => {
-  if (isFull) {
+  if (isFull.value) {
     width.value /= 3;
     height.value /= 3;
   } else {
     width.value *= 3;
     height.value *= 3;
   }
-  isFull = !isFull;
+  isFull.value = !isFull.value;
 };
 
 let unMoveHandler: () => void;

+ 3 - 4
src/example/components/slide/actions.ts

@@ -59,12 +59,11 @@ export const imp: MenuItem = {
   icon: 'import',
   name: "导入",
   value: uuid(),
-  type: 'sub-menu-horizontal',
   children: [
     {
       value: uuid(),
       icon: "scene_i",
-      name: "场景导入",
+      name: "场景",
       handler: async (draw: Draw) => {
         const aiData = await selectAI();
         drawPlatformResource(aiData, draw);
@@ -73,7 +72,7 @@ export const imp: MenuItem = {
     {
       value: uuid(),
       icon: "local_i",
-      name: "本地上传",
+      name: "本地",
       handler: async (draw: Draw) => {
         const files = await selectFile()
         const url = await uploadResourse(files[0])
@@ -83,7 +82,7 @@ export const imp: MenuItem = {
           {
             width: image.width,
             height: image.height,
-            url: URL.createObjectURL(files[0]),
+            url
           },
           { x: window.innerWidth / 2, y: window.innerHeight / 2 },
           true

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

@@ -22,7 +22,7 @@ export const props = reactive({
 export const selectAI = () =>
   new Promise<AIExposeData>((resolve, reject) => {
     props.content = markRaw(AI);
-    props.title = "选择场景";
+    props.title = "选择场景";
     props.visiable = true;
     props.submit = (info) => {
       resolve(info);

+ 1 - 2
src/example/dialog/basemap/gd-map/selectAMapImage.vue

@@ -8,7 +8,7 @@
       clearable
     >
       <template #append>
-        <el-button :icon="Search" />
+        <ui-icon name="search" />
       </template>
     </el-input>
     <div class="rrr">
@@ -37,7 +37,6 @@
 <script setup lang="ts">
 import AMapLoader from "@amap/amap-jsapi-loader";
 import { ElInput, ElButton } from "element-plus";
-import { Search } from "@element-plus/icons-vue";
 import { ref, watch } from "vue";
 import { analysisGPS, debounce } from "@/utils/shared";
 import { Size } from "@/utils/math";

+ 1 - 1
src/example/dialog/vr/vr.vue

@@ -1,7 +1,7 @@
 <template>
   <div style="padding: 20px 20px 40px">
     <p class="title">
-      {{ label ? label : "选择场景" }}
+      {{ label ? label : "选择场景" }}
     </p>
     <el-select
       :model-value="value?.id"

+ 5 - 9
src/example/fuse/router.ts

@@ -1,22 +1,18 @@
 import { createRouter, createWebHashHistory } from "vue-router";
 
 import Overview from "./views/overview/index.vue";
+import OverviewQuery from "./views/overview/query.vue";
 import Tabulation from "./views/tabulation/index.vue";
-import { watchEffect } from "vue";
+import QueryTabulation from "./views/tabulation/query.vue";
 
 export const history = createWebHashHistory();
 export const router = createRouter({
   history,
   routes: [
     { path: "/overview", name: "overview", component: Overview },
+    { path: "/query/overview", name: "query-overview", component: OverviewQuery },
     { path: "/tabulation", name: "tabulation", component: Tabulation },
+    { path: "/query/tabulation", name: "query-tabulation", component: QueryTabulation },
+    { path: '/:pathMatch(.*)*',  redirect: '/query/overview' } 
   ],
 });
-
-setTimeout(() => {
-  watchEffect(() => {
-    if (!router.currentRoute.value.name) {
-      router.replace({ name: "overview" });
-    }
-  });
-}, 3000);

+ 3 - 1
src/example/fuse/views/overview/header.vue

@@ -28,7 +28,7 @@ import { getRepTabulationStore } from "../tabulation/gen.ts";
 import { getPaperConfig, paperConfigs } from "@/example/components/slide/actions.ts";
 import { DataGroupId } from "@/constant/index.ts";
 import { Group } from "konva/lib/Group";
-import { asyncTimeout } from "@/utils/shared.ts";
+import { Mode } from "@/constant/mode.ts";
 
 const draw = useDraw();
 
@@ -66,6 +66,7 @@ const setViewToTableCover = async () => {
   const oldShowCompass = draw.config.showCompass;
   const oldLabelLineConfig = { ...draw.config.labelLineConfig };
 
+  const pop = draw.mode.push(Mode.readonly);
   const rect = draw.stage!.findOne<Group>(`#${DataGroupId}`)!.getClientRect();
   const rectScale = rect.width / rect.height;
   const tableCoverScale = 540 / 425;
@@ -94,6 +95,7 @@ const setViewToTableCover = async () => {
   draw.initViewport();
 
   return () => {
+    pop();
     draw.config.size = oldSize;
     draw.config.showGrid = oldShowGrid;
     draw.config.back = oldBack;

+ 0 - 1
src/example/fuse/views/overview/index.vue

@@ -39,7 +39,6 @@ const init = async (draw: Draw) => {
   draw.config.showCompass = false;
   draw.config.showLabelLine = true;
   draw.config.showComponentSize = true;
-  console.log("0.0.0");
   draw.config.back = { color: "#f0f2f5", opacity: 1 };
   draw.store.setStore(overviewData.value.store);
   overviewData.value.viewport && draw.viewer.setViewMat(overviewData.value.viewport);

+ 41 - 0
src/example/fuse/views/overview/query.vue

@@ -0,0 +1,41 @@
+<template>
+  <Container
+    class="query-container"
+    :upload-resourse="uploadResourse"
+    :full="false"
+    :ref="(d: any) => (draw = d?.draw)"
+  />
+</template>
+
+<script lang="ts" setup>
+import Container from "../../../components/container/container.vue";
+import { uploadResourse } from "../../req";
+import { ref, watch } from "vue";
+import { Draw } from "../../../components/container/use-draw";
+import { refreshOverviewData, overviewData } from "../../store";
+import { Mode } from "@/constant/mode";
+
+const draw = ref<Draw>();
+
+const init = async (draw: Draw) => {
+  await refreshOverviewData();
+  draw.config.showCompass = false;
+  draw.config.showLabelLine = true;
+  draw.config.showComponentSize = true;
+  draw.config.back = { color: "#f0f2f5", opacity: 1 };
+  draw.mode.push(Mode.readonly);
+  draw.store.setStore(overviewData.value.store);
+  overviewData.value.viewport && draw.viewer.setViewMat(overviewData.value.viewport);
+};
+
+watch(draw, (draw) => draw && init(draw));
+</script>
+
+<style lang="scss" scoped>
+@use '../../../styles/global';
+
+.query-container {
+  --top: calc(-1 * #{global.$headerSize});
+  --left: calc(-1 * #{global.$slideSize});
+}
+</style>

+ 5 - 2
src/example/fuse/views/tabulation/gen.ts

@@ -5,9 +5,10 @@ import { getFixPosition } from "@/utils/bound";
 import { Size } from "@/utils/math";
 import { getImage } from "@/utils/resource";
 import { tableCoverKey, tableTableKey, tableTitleKey } from "../../store";
-import { TableData } from "@/core/components/table";
+import { matResponse, TableData } from "@/core/components/table";
 import { TextData } from "@/core/components/text";
 import { ImageData } from "@/core/components/image";
+import { Transform } from "konva/lib/Util";
 
 const setCoverPosition = (
   size: Size,
@@ -106,7 +107,8 @@ const genDefaultTable = () => {
     fontColor: "#000000",
   };
   const valueColl = { ...nameColl, width: 200 };
-  return {
+  
+  const data = {
     ...getBaseItem(),
     lock: true,
     content: [
@@ -121,6 +123,7 @@ const genDefaultTable = () => {
     height: nameColl.height * 5,
     mat: [1, 0, 0, 1, 0, 0],
   };
+  return matResponse({ data, mat: new Transform() })
 };
 
 export const genDefaultTitle = () => {

+ 3 - 0
src/example/fuse/views/tabulation/header.vue

@@ -20,6 +20,7 @@ import { jsPDF } from "jspdf";
 import { getImage as getResourceImage } from "@/utils/resource.ts";
 import { nextTick } from "vue";
 import { tabulationData } from "../../store.ts";
+import { Mode } from "@/constant/mode.ts";
 
 const draw = useDraw();
 
@@ -41,6 +42,7 @@ const actions = [
         const ef = await selectExposeFormat();
         const format = "image/jpeg";
         let [rect, fileBlob] = await draw.enterTemp(async () => {
+          const pop = draw.mode.push(Mode.readonly);
           const oldMat = draw.viewer.viewMat;
           draw.viewer.setViewMat([1, 0, 0, 1, 0, 0]);
           await nextTick();
@@ -63,6 +65,7 @@ const actions = [
             ...rect,
           }) as Promise<Blob>);
           draw.viewer.setViewMat(oldMat);
+          pop();
           return [rect, fileBlob] as const;
         });
 

+ 1 - 7
src/example/fuse/views/tabulation/index.vue

@@ -5,14 +5,11 @@
     :ref="(d: any) => (draw = d?.draw)"
   >
     <template #header>
-      <Header @selectVR="(scene) => (vrScene = scene)" v-if="inited" />
+      <Header v-if="inited" />
     </template>
     <template #slide>
       <Slide v-if="inited" />
     </template>
-    <template #cover>
-      <ShowVR :scene="vrScene" v-if="vrScene" ref="vr" @close="vrScene = undefined" />
-    </template>
   </Container>
 
   <Dialog />
@@ -22,17 +19,14 @@
 import Header from "./header.vue";
 import Slide from "./slide.vue";
 import Container from "../../../components/container/container.vue";
-import ShowVR from "../../../components/show-vr.vue";
 import { uploadResourse } from "../../req";
 import { ref, watch } from "vue";
 import { Draw } from "../../../components/container/use-draw";
-import { Scene } from "../../../platform/platform-resource";
 import Dialog from "../../../dialog/dialog.vue";
 import { tabulationData, refreshTabulationData } from "../../store";
 
 const full = ref(false);
 const draw = ref<Draw>();
-const vrScene = ref<Scene>();
 
 const inited = ref(false);
 const init = async (draw: Draw) => {

+ 43 - 0
src/example/fuse/views/tabulation/query.vue

@@ -0,0 +1,43 @@
+<template>
+  <Container
+    class="query-container"
+    :upload-resourse="uploadResourse"
+    :full="false"
+    :ref="(d: any) => (draw = d?.draw)"
+  />
+</template>
+
+<script lang="ts" setup>
+import Container from "../../../components/container/container.vue";
+import { uploadResourse } from "../../req";
+import { ref, watch } from "vue";
+import { Draw } from "../../../components/container/use-draw";
+import { tabulationData, refreshTabulationData } from "../../store";
+import { Mode } from "@/constant/mode";
+import { paper } from "@/example/components/slide/actions";
+
+const draw = ref<Draw>();
+const init = async (draw: Draw) => {
+  await refreshTabulationData();
+  draw.config.showCompass = true;
+  draw.config.showGrid = false;
+  draw.config.showLabelLine = false;
+  draw.config.showComponentSize = false;
+  draw.mode.push(Mode.readonly);
+  paper.children
+    .find((item) => item.key === tabulationData.value.paperKey)
+    ?.handler(draw);
+  draw.store.setStore(tabulationData.value.store);
+};
+
+watch(draw, (draw) => draw && init(draw));
+</script>
+
+<style lang="scss" scoped>
+@use '../../../styles/global';
+
+.query-container {
+  --top: calc(-1 * #{global.$headerSize});
+  --left: calc(-1 * #{global.$slideSize});
+}
+</style>

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

@@ -2,6 +2,7 @@
 
 $headerSize: 60px;
 $slideSize: 64px;
+$bottomSize: 50px;
 
 * {
 	box-sizing: border-box;

+ 2 - 1
src/utils/resource.ts

@@ -9,7 +9,7 @@ export let getImage = (url: string): Promise<HTMLImageElement> => {
   imageCache1 = {};
   getImage = (url: string) => {
     if (url in imageCache) {
-      if (imageCache1[url].width === 0 || imageCache1[url].height === 0) {
+      if (imageCache1[url]?.width === 0 || imageCache1[url]?.height === 0) {
         delete imageCache1[url]
         delete imageCache[url];
         delete imageInfo[url]
@@ -19,6 +19,7 @@ export let getImage = (url: string): Promise<HTMLImageElement> => {
     } 
     return (imageCache[url] = new Promise((resolve, reject) => {
       const image = new Image();
+      image.crossOrigin = "anonymous";
       image.onload = () => {
         resolve(image);
         imageInfo[url] = {