13 Commits db1f9903dd ... 2877e3c40d

Auteur SHA1 Message Date
  lianghongjie 2877e3c40d 修复iOS低版本无法打开的bug, 优化尺寸编辑UI il y a 1 an
  lianghongjie 885b956963 Merge branch 'dev' of http://124.70.149.18:10880/lianghj/queenshow into dev-lhj il y a 1 an
  liwei 90917e1879 udpate il y a 1 an
  liwei f0bd12ccc3 Merge remote-tracking branch 'origin/dev-lhj' into dev il y a 1 an
  liwei 4d6f9cc5c8 修复层级的bug il y a 1 an
  liwei 5157094e29 更新livetoolbar il y a 1 an
  lianghongjie 29c8941df0 Merge branch 'dev' of http://124.70.149.18:10880/lianghj/queenshow into dev-lhj il y a 1 an
  bianjiang f5bd373b03 Merge branch 'dev' of http://124.70.149.18:10880/lianghj/queenshow into dev il y a 1 an
  bianjiang 8d682c77f1 letter il y a 1 an
  liwei 986c9f570a Merge branch 'dev' of http://124.70.149.18:10880/lianghj/queenshow into dev il y a 1 an
  liwei cfa1d16d84 添加动画预览 il y a 1 an
  bianjiang 8e0e2fd3ce Merge branch 'dev' of http://124.70.149.18:10880/lianghj/queenshow into dev il y a 1 an
  bianjiang c48ab49550 eidtor il y a 1 an
43 fichiers modifiés avec 682 ajouts et 556 suppressions
  1. 1 0
      .browserslistrc
  2. 1 0
      babel.config.js
  3. 1 0
      package.json
  4. 1 1
      src/assets/icons/components/IconCroperr.tsx
  5. 3 0
      src/assets/icons/components/IconDelete.tsx
  6. 1 25
      src/assets/icons/components/IconLayerDown.tsx
  7. 16 21
      src/assets/icons/components/IconLayerUp.tsx
  8. 3 0
      src/assets/icons/components/IconRelate.tsx
  9. 3 0
      src/assets/icons/components/IconTextLink.tsx
  10. 3 0
      src/assets/icons/index.ts
  11. 1 1
      src/assets/icons/svg/croperr.svg
  12. 1 0
      src/assets/icons/svg/delete.svg
  13. 1 25
      src/assets/icons/svg/layerDown.svg
  14. 16 21
      src/assets/icons/svg/layerUp.svg
  15. 1 0
      src/assets/icons/svg/relate.svg
  16. 1 0
      src/assets/icons/svg/textLink.svg
  17. 5 1
      src/modules/editor/components/CompUI/basicUI/Text/EditorCustom.ts
  18. 49 132
      src/modules/editor/components/CompUI/basicUI/Text/TextToolComp.tsx
  19. 30 41
      src/modules/editor/components/CompUI/basicUI/Text/TextToolForm.tsx
  20. 0 164
      src/modules/editor/components/CompUI/basicUI/Text/TextToolUI.tsx
  21. 4 9
      src/modules/editor/components/CompUI/basicUI/Text/ckeditor-letter-spacing/LetterSpacingCommand.ts
  22. 14 11
      src/modules/editor/components/CompUI/basicUI/Text/ckeditor-letter-spacing/LetterSpacingEditing.ts
  23. 112 0
      src/modules/editor/components/CompUI/basicUI/Text/ckeditor-letter-spacing/LetterSpacingUI.ts
  24. 66 0
      src/modules/editor/components/CompUI/basicUI/Text/ckeditor-letter-spacing/utils.ts
  25. 3 2
      src/modules/editor/components/CompUI/basicUI/Text/component2.tsx
  26. 18 16
      src/modules/editor/components/CompUI/basicUI/Transfer/select.tsx
  27. 4 0
      src/modules/editor/components/CompUI/basicUI/View.tsx
  28. 31 0
      src/modules/editor/components/CompUI/defines/align.tsx
  29. 2 6
      src/modules/editor/components/CompUI/defines/createAttrsForm.tsx
  30. 129 55
      src/modules/editor/components/CompUI/formItems/Size.tsx
  31. 12 10
      src/modules/editor/components/TipIcons/index.ts
  32. 0 2
      src/modules/editor/components/index.ts
  33. 66 0
      src/modules/editor/controllers/AnimCtrl/index.ts
  34. 15 0
      src/modules/editor/controllers/TextEditorCtrl/index.ts
  35. 21 4
      src/modules/editor/module/actions/edit.tsx
  36. 5 0
      src/modules/editor/module/helpers/index.ts
  37. 5 1
      src/modules/editor/module/index.ts
  38. 2 0
      src/modules/editor/objects/DesignTemp/DesignComp.ts
  39. 2 2
      src/modules/editor/objects/DesignTemp/creates/createCompStyle.ts
  40. 7 3
      src/modules/editor/objects/Toolbars/default.ts
  41. 21 0
      src/modules/editor/objects/Toolbars/liveTools.ts
  42. 3 2
      src/modules/editor/typings.ts
  43. 2 1
      src/pages/editor/EditPage/index.tsx

+ 1 - 0
.browserslistrc

@@ -2,3 +2,4 @@
 last 2 versions
 not dead
 not ie 11
+ios >= 9

+ 1 - 0
babel.config.js

@@ -7,5 +7,6 @@ module.exports = {
       { libraryName: "ant-design-vue", libraryDirectory: "es", style: true },
       "antd",
     ],
+    "@babel/plugin-proposal-class-properties"
   ],
 };

+ 1 - 0
package.json

@@ -16,6 +16,7 @@
   },
   "dependencies": {
     "@amap/amap-jsapi-loader": "^1.0.1",
+    "@babel/plugin-proposal-class-properties": "^7.18.6",
     "@ckeditor/ckeditor5-alignment": "^38.0.0",
     "@ckeditor/ckeditor5-basic-styles": "^38.0.0",
     "@ckeditor/ckeditor5-build-classic": "^38.0.1",

+ 1 - 1
src/assets/icons/components/IconCroperr.tsx

@@ -1,3 +1,3 @@
 
 import { createIcon } from '@queenjs/icons';
-export const IconCroperr = createIcon(<svg viewBox="0 0 15.143 14.943"><g transform="translate(-828.872 -93.985)"><g transform="translate(824.5 89.62)"><rect fill="none" stroke="currentColor" stroke-linejoin="round" width="7.631" height="7.631" rx="1" transform="translate(5.072 11.177)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M30,6h4.579v4.579" transform="translate(-15.771 -0.928)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M6,30.79l2.335-1.751a1.145,1.145,0,0,1,1.412.03l3.5,2.866" transform="translate(-0.928 -15.035)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M34.579,6,30,10.579" transform="translate(-15.771 -0.928)"/></g><g transform="translate(823.572 88.692)"><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M7.483,6H6V7.507"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M16.028,6h1.921" transform="translate(-6.283)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M6,16v.664" transform="translate(0 -6.265)"/></g><g transform="translate(828.344 93.463)"><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M6,27.5H7.493V26.012" transform="translate(7.471 -12.537)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M30,16v1.444" transform="translate(-15.035 -6.695)"/><path fill="none" stroke="currentColor" stroke-linecap="round" d="M15.992,30h.66" transform="translate(-5.266 -15.035)"/></g></g></svg>)
+export const IconCroperr = createIcon(<svg  viewBox="0 0 34 34"><g transform="translate(-946 -264)"><rect fill="none" width="34" height="34" rx="6" transform="translate(946 264)"/><g transform="translate(954.257 272.257)"><g transform="translate(0 0)"><rect fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" width="9.715" height="9.715" rx="1" transform="translate(0 7.772)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M30,6h5.829v5.829" transform="translate(-18.342 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M6,31.331,8.973,29.1a1.457,1.457,0,0,1,1.8.038l4.46,3.649" transform="translate(-6 -17.73)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M35.829,6,30,11.829" transform="translate(-18.342 -6)"/></g><g transform="translate(0 0)"><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M7.887,6H6V7.918" transform="translate(-6 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M16.028,6h2.446" transform="translate(-11.26 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M6,16v.845" transform="translate(-6 -11.245)"/></g><g transform="translate(12.092 10.281)"><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M6,27.908H7.9v-1.9" transform="translate(-2.507 -20.703)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M30,16v1.838" transform="translate(-24.605 -16)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M15.992,30h.84" transform="translate(-15.992 -22.794)"/></g></g></g></svg>)

+ 3 - 0
src/assets/icons/components/IconDelete.tsx

@@ -0,0 +1,3 @@
+
+import { createIcon } from '@queenjs/icons';
+export const IconDelete = createIcon(<svg viewBox="0 0 34 34"><g transform="translate(-1070 -264)"><rect fill="none" width="34" height="34" rx="6" transform="translate(1070 264)"/><g transform="translate(1078.443 272.232)"><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" d="M15,8.328,15.57,5h7.416l.57,3.328" transform="translate(-10.721 -5)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M6,12H23.115" transform="translate(-6 -8.672)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" fill-rule="evenodd" d="M23.361,12h0V26.209H11V12Z" transform="translate(-8.623 -8.672)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M19,35h4.754" transform="translate(-12.82 -20.834)"/></g></g></svg>)

+ 1 - 25
src/assets/icons/components/IconLayerDown.tsx

@@ -1,27 +1,3 @@
 
 import { createIcon } from '@queenjs/icons';
-export const IconLayerDown = createIcon(<svg viewBox="0 0 14.469 14.474">
-  <g transform="translate(-1332.776 -243.777)">
-    <g transform="translate(1327.276 238.277)">
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M7.483,6H6V7.507" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M7.493,27.5H6v-1.49" transform="translate(0 -12.537)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M6,27.5H7.493V26.012" transform="translate(7.471 -12.537)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M26,6H27.5V7.5" transform="translate(-12.531)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M16.028,6h1.487" transform="translate(-6.283)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M6,16v1.494"
-        transform="translate(0 -6.265)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M30,16v1.121" transform="translate(-15.035 -6.265)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" d="M15.992,30h1.5"
-        transform="translate(-6.26 -15.035)" />
-    </g>
-    <path fill="none" stroke="currentColor" stroke-linejoin="round"
-      d="M16162.748,4984.224v4.527h9v-8.966h-4.534" transform="translate(-14825 -4731)" />
-  </g>
-</svg>)
+export const IconLayerDown = createIcon(<svg viewBox="0 0 34 34"><g transform="translate(-1029 -264)"><rect fill="none" width="34" height="34" rx="6" transform="translate(1029 264)"/><g transform="translate(1037.428 272.423)"><g transform="translate(0)"><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M7.887,6H6V7.918" transform="translate(-6 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M7.9,27.908H6v-1.9" transform="translate(-6 -16.496)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M6,27.908H7.9v-1.9" transform="translate(3.511 -16.496)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M26,6h1.9V7.909" transform="translate(-16.491 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M16.028,6h1.893" transform="translate(-11.26 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M6,16v1.9" transform="translate(-6 -11.245)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M30,16v1.427" transform="translate(-18.587 -11.245)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M15.992,30H17.9" transform="translate(-11.241 -18.587)"/></g><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" d="M16162.749,4985.436v5.764h11.451v-11.415h-5.77" transform="translate(-16157.056 -4974.045)"/></g></g></svg>)

+ 16 - 21
src/assets/icons/components/IconLayerUp.tsx

@@ -1,24 +1,19 @@
 
 import { createIcon } from '@queenjs/icons';
-export const IconLayerUp = createIcon(<svg viewBox="0 0 14.469 14.474">
-  <g transform="translate(-5.5 -5.5)">
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M7.483,6H6V7.507" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M7.493,27.5H6v-1.49" transform="translate(0 -12.537)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M26,6H27.5V7.5" transform="translate(-12.531)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M16.028,6h1.487" transform="translate(-6.283)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M6,16v1.494"
-      transform="translate(0 -6.265)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M30,16v.56"
-      transform="translate(-15.035 -6.265)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" d="M15.992,30h.75"
-      transform="translate(-6.26 -15.035)" />
-    <path fill="none" stroke="currentColor" stroke-linejoin="round"
-      d="M16162.748,4984.224v4.527h9v-8.966h-9Z" transform="translate(-16152.276 -4969.277)" />
-  </g>
+export const IconLayerUp = createIcon(<svg viewBox="0 0 34 34">
+    
+    <g transform="translate(-988 -264)">
+        <rect fill="none" width="34" height="34" rx="6" transform="translate(988 264)" />
+        <g transform="translate(996.428 272.423)">
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M7.887,6H6V7.918" transform="translate(-6 -6)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M7.9,27.908H6v-1.9" transform="translate(-6 -16.496)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M26,6h1.9V7.909" transform="translate(-16.491 -6)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M16.028,6h1.893" transform="translate(-11.26 -6)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M6,16v1.9" transform="translate(-6 -11.245)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M30,16v.713" transform="translate(-18.587 -11.245)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M15.992,30h.955" transform="translate(-11.241 -18.587)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" d="M16162.749,4985.436v5.764h11.451v-11.415h-11.451Z"
+                transform="translate(-16157.056 -4974.045)" />
+        </g>
+    </g>
 </svg>)

+ 3 - 0
src/assets/icons/components/IconRelate.tsx

@@ -0,0 +1,3 @@
+
+import { createIcon } from '@queenjs/icons';
+export const IconRelate = createIcon(<svg viewBox="0 0 22 22"><g transform="translate(-2783 -4497)"><rect fill="none" width="22" height="22" transform="translate(2783 4497)"/><g transform="translate(2800.435 4511.481) rotate(180)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" d="M-189.919,68.962h-2.6A3.491,3.491,0,0,1-196,65.481h0A3.491,3.491,0,0,1-192.519,62h2.6" transform="translate(194 -62)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" d="M-196,68.962h2.6a3.491,3.491,0,0,0,3.481-3.481h0A3.491,3.491,0,0,0-193.4,62H-196" transform="translate(204.354 -62)"/></g></g></svg>)

+ 3 - 0
src/assets/icons/components/IconTextLink.tsx

@@ -0,0 +1,3 @@
+
+import { createIcon } from '@queenjs/icons';
+export const IconTextLink = createIcon(<svg viewBox="0 0 34 34"><g transform="translate(-1070 -264)"><rect fill="none" width="34" height="34" rx="6" transform="translate(1070 264)"/><g transform="translate(1075.875 284.886) rotate(-45)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-miterlimit="10" d="M8.943,10.238H5.119A5.134,5.134,0,0,1,0,5.119H0A5.134,5.134,0,0,1,5.119,0H8.943" transform="translate(0 0)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-miterlimit="10" d="M0,10.238H3.824A5.134,5.134,0,0,0,8.943,5.119h0A5.134,5.134,0,0,0,3.824,0H0" transform="translate(12.286 0)"/></g><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M0,0H7.1" transform="translate(1084.489 283.511) rotate(-45)"/></g></svg>)

+ 3 - 0
src/assets/icons/index.ts

@@ -20,6 +20,7 @@ export * from "./components/IconCombination";
 export * from "./components/IconCroperr";
 export * from "./components/IconCross";
 export * from "./components/IconCube";
+export * from "./components/IconDelete";
 export * from "./components/IconEmpty";
 export * from "./components/IconFloatOff";
 export * from "./components/IconFloatOn";
@@ -37,6 +38,7 @@ export * from "./components/IconPlay2";
 export * from "./components/IconPreview";
 export * from "./components/IconProfile";
 export * from "./components/IconQueen";
+export * from "./components/IconRelate";
 export * from "./components/IconResizeY";
 export * from "./components/IconRight";
 export * from "./components/IconRotate";
@@ -52,6 +54,7 @@ export * from "./components/IconTextJustify";
 export * from "./components/IconTextLeft";
 export * from "./components/IconTextLetterSpacing";
 export * from "./components/IconTextLineHeight";
+export * from "./components/IconTextLink";
 export * from "./components/IconTextRight";
 export * from "./components/IconTextSize";
 export * from "./components/IconTextUnderline";

+ 1 - 1
src/assets/icons/svg/croperr.svg

@@ -1 +1 @@
-<svg viewBox="0 0 15.143 14.943"><g transform="translate(-828.872 -93.985)"><g transform="translate(824.5 89.62)"><rect fill="none" stroke="currentColor" stroke-linejoin="round" width="7.631" height="7.631" rx="1" transform="translate(5.072 11.177)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M30,6h4.579v4.579" transform="translate(-15.771 -0.928)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M6,30.79l2.335-1.751a1.145,1.145,0,0,1,1.412.03l3.5,2.866" transform="translate(-0.928 -15.035)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M34.579,6,30,10.579" transform="translate(-15.771 -0.928)"/></g><g transform="translate(823.572 88.692)"><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M7.483,6H6V7.507"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M16.028,6h1.921" transform="translate(-6.283)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M6,16v.664" transform="translate(0 -6.265)"/></g><g transform="translate(828.344 93.463)"><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M6,27.5H7.493V26.012" transform="translate(7.471 -12.537)"/><path fill="none" stroke="currentColor" stroke-linejoin="round" stroke-linecap="round" d="M30,16v1.444" transform="translate(-15.035 -6.695)"/><path fill="none" stroke="currentColor" stroke-linecap="round" d="M15.992,30h.66" transform="translate(-5.266 -15.035)"/></g></g></svg>
+<svg  viewBox="0 0 34 34"><g transform="translate(-946 -264)"><rect fill="none" width="34" height="34" rx="6" transform="translate(946 264)"/><g transform="translate(954.257 272.257)"><g transform="translate(0 0)"><rect fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" width="9.715" height="9.715" rx="1" transform="translate(0 7.772)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M30,6h5.829v5.829" transform="translate(-18.342 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M6,31.331,8.973,29.1a1.457,1.457,0,0,1,1.8.038l4.46,3.649" transform="translate(-6 -17.73)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M35.829,6,30,11.829" transform="translate(-18.342 -6)"/></g><g transform="translate(0 0)"><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M7.887,6H6V7.918" transform="translate(-6 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M16.028,6h2.446" transform="translate(-11.26 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M6,16v.845" transform="translate(-6 -11.245)"/></g><g transform="translate(12.092 10.281)"><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M6,27.908H7.9v-1.9" transform="translate(-2.507 -20.703)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" d="M30,16v1.838" transform="translate(-24.605 -16)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M15.992,30h.84" transform="translate(-15.992 -22.794)"/></g></g></g></svg>

+ 1 - 0
src/assets/icons/svg/delete.svg

@@ -0,0 +1 @@
+<svg viewBox="0 0 34 34"><g transform="translate(-1070 -264)"><rect fill="none" width="34" height="34" rx="6" transform="translate(1070 264)"/><g transform="translate(1078.443 272.232)"><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" d="M15,8.328,15.57,5h7.416l.57,3.328" transform="translate(-10.721 -5)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M6,12H23.115" transform="translate(-6 -8.672)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" stroke-linecap="round" fill-rule="evenodd" d="M23.361,12h0V26.209H11V12Z" transform="translate(-8.623 -8.672)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M19,35h4.754" transform="translate(-12.82 -20.834)"/></g></g></svg>

+ 1 - 25
src/assets/icons/svg/layerDown.svg

@@ -1,25 +1 @@
-<svg viewBox="0 0 14.469 14.474">
-  <g transform="translate(-1332.776 -243.777)">
-    <g transform="translate(1327.276 238.277)">
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M7.483,6H6V7.507" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M7.493,27.5H6v-1.49" transform="translate(0 -12.537)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M6,27.5H7.493V26.012" transform="translate(7.471 -12.537)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M26,6H27.5V7.5" transform="translate(-12.531)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M16.028,6h1.487" transform="translate(-6.283)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M6,16v1.494"
-        transform="translate(0 -6.265)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-        d="M30,16v1.121" transform="translate(-15.035 -6.265)" />
-      <path fill="none" stroke="currentColor" stroke-linecap="round" d="M15.992,30h1.5"
-        transform="translate(-6.26 -15.035)" />
-    </g>
-    <path fill="none" stroke="currentColor" stroke-linejoin="round"
-      d="M16162.748,4984.224v4.527h9v-8.966h-4.534" transform="translate(-14825 -4731)" />
-  </g>
-</svg>
+<svg viewBox="0 0 34 34"><g transform="translate(-1029 -264)"><rect fill="none" width="34" height="34" rx="6" transform="translate(1029 264)"/><g transform="translate(1037.428 272.423)"><g transform="translate(0)"><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M7.887,6H6V7.918" transform="translate(-6 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M7.9,27.908H6v-1.9" transform="translate(-6 -16.496)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M6,27.908H7.9v-1.9" transform="translate(3.511 -16.496)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M26,6h1.9V7.909" transform="translate(-16.491 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M16.028,6h1.893" transform="translate(-11.26 -6)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M6,16v1.9" transform="translate(-6 -11.245)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M30,16v1.427" transform="translate(-18.587 -11.245)"/><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M15.992,30H17.9" transform="translate(-11.241 -18.587)"/></g><path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" d="M16162.749,4985.436v5.764h11.451v-11.415h-5.77" transform="translate(-16157.056 -4974.045)"/></g></g></svg>

+ 16 - 21
src/assets/icons/svg/layerUp.svg

@@ -1,22 +1,17 @@
-<svg viewBox="0 0 14.469 14.474">
-  <g transform="translate(-5.5 -5.5)">
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M7.483,6H6V7.507" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M7.493,27.5H6v-1.49" transform="translate(0 -12.537)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M26,6H27.5V7.5" transform="translate(-12.531)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M16.028,6h1.487" transform="translate(-6.283)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M6,16v1.494"
-      transform="translate(0 -6.265)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
-      d="M30,16v.56"
-      transform="translate(-15.035 -6.265)" />
-    <path fill="none" stroke="currentColor" stroke-linecap="round" d="M15.992,30h.75"
-      transform="translate(-6.26 -15.035)" />
-    <path fill="none" stroke="currentColor" stroke-linejoin="round"
-      d="M16162.748,4984.224v4.527h9v-8.966h-9Z" transform="translate(-16152.276 -4969.277)" />
-  </g>
+<svg viewBox="0 0 34 34">
+    
+    <g transform="translate(-988 -264)">
+        <rect fill="none" width="34" height="34" rx="6" transform="translate(988 264)" />
+        <g transform="translate(996.428 272.423)">
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M7.887,6H6V7.918" transform="translate(-6 -6)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M7.9,27.908H6v-1.9" transform="translate(-6 -16.496)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M26,6h1.9V7.909" transform="translate(-16.491 -6)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M16.028,6h1.893" transform="translate(-11.26 -6)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M6,16v1.9" transform="translate(-6 -11.245)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" stroke-linejoin="round" d="M30,16v.713" transform="translate(-18.587 -11.245)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linecap="round" d="M15.992,30h.955" transform="translate(-11.241 -18.587)" />
+            <path fill="none" stroke="currentColor" stroke-width="1.2px" stroke-linejoin="round" d="M16162.749,4985.436v5.764h11.451v-11.415h-11.451Z"
+                transform="translate(-16157.056 -4974.045)" />
+        </g>
+    </g>
 </svg>

+ 1 - 0
src/assets/icons/svg/relate.svg

@@ -0,0 +1 @@
+<svg viewBox="0 0 22 22"><g transform="translate(-2783 -4497)"><rect fill="none" width="22" height="22" transform="translate(2783 4497)"/><g transform="translate(2800.435 4511.481) rotate(180)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" d="M-189.919,68.962h-2.6A3.491,3.491,0,0,1-196,65.481h0A3.491,3.491,0,0,1-192.519,62h2.6" transform="translate(194 -62)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" d="M-196,68.962h2.6a3.491,3.491,0,0,0,3.481-3.481h0A3.491,3.491,0,0,0-193.4,62H-196" transform="translate(204.354 -62)"/></g></g></svg>

+ 1 - 0
src/assets/icons/svg/textLink.svg

@@ -0,0 +1 @@
+<svg viewBox="0 0 34 34"><g transform="translate(-1070 -264)"><rect fill="none" width="34" height="34" rx="6" transform="translate(1070 264)"/><g transform="translate(1075.875 284.886) rotate(-45)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-miterlimit="10" d="M8.943,10.238H5.119A5.134,5.134,0,0,1,0,5.119H0A5.134,5.134,0,0,1,5.119,0H8.943" transform="translate(0 0)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-miterlimit="10" d="M0,10.238H3.824A5.134,5.134,0,0,0,8.943,5.119h0A5.134,5.134,0,0,0,3.824,0H0" transform="translate(12.286 0)"/></g><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M0,0H7.1" transform="translate(1084.489 283.511) rotate(-45)"/></g></svg>

+ 5 - 1
src/modules/editor/components/CompUI/basicUI/Text/EditorCustom.ts

@@ -19,6 +19,7 @@ import { EditorConfig } from "@ckeditor/ckeditor5-core";
 export class HeadlessEditor extends DecoupledEditorBase {}
 interface HeadlessConfig extends EditorConfig {
   lineHeight: any;
+  letterSpacing: any;
 }
 HeadlessEditor.builtinPlugins = [
   Essentials,
@@ -59,7 +60,10 @@ HeadlessEditor.defaultConfig = {
     supportAllValues: true,
   },
   lineHeight: {
-    options: [1, 1.5, 2, 2.5, 3],
+    options: [0.5, 1, 1.5, 2, 2.5, 3],
+  },
+  letterSpacing: {
+    options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
   },
   link: {},
 } as HeadlessConfig;

+ 49 - 132
src/modules/editor/components/CompUI/basicUI/Text/TextToolComp.tsx

@@ -1,19 +1,20 @@
 import {
+  IconStrikethrough,
+  IconTextBold,
   IconTextCenter,
+  IconTextItalic,
   IconTextJustify,
   IconTextLeft,
   IconTextLetterSpacing,
   IconTextLineHeight,
   IconTextRight,
   IconTextSize,
-  IconStrikethrough,
-  IconTextBold,
-  IconTextItalic,
   IconTextUnderline,
 } from "@/assets/icons";
 import { css } from "@linaria/core";
-import { Button, Input, InputNumber, Tooltip } from "ant-design-vue";
+import { Button, InputNumber, Tooltip } from "ant-design-vue";
 
+import { useEditor } from "@/modules/editor";
 import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select";
 import "@simonwep/pickr/dist/themes/nano.min.css";
 import _ from "lodash";
@@ -24,10 +25,10 @@ import {
   onUnmounted,
   reactive,
   ref,
+  toRaw,
   watch,
 } from "vue";
 import { any, bool, func, number, object, string } from "vue-types";
-import { useEditor } from "@/modules/editor";
 interface ColumnItem {
   label?: string;
   component?: ((...args: any[]) => any) | Record<string, any>;
@@ -36,104 +37,7 @@ interface ColumnItem {
   itemProps?: { [name: string]: any };
   changeExtra?: (data: any) => any;
 }
-// export const TextColor = defineComponent({
-//   props: {
-//     value: string().def("#666666"),
-//   },
-//   emits: ["change"],
-//   setup(props, { emit }) {
-//     let picker: any = null;
 
-//     let emitFlagRef = ref(true);
-//     const color = HSLToHex(props.value);
-//     function HSLToHex(hslStr: string): string {
-//       const isHsl = hslStr.indexOf("hsl");
-//       if (isHsl == -1) {
-//         return hslStr;
-//       }
-//       const reg = /(?<=hsl\()(\W|\w)*(?=\))/g;
-//       let hsl: any = hslStr.match(reg);
-//       if (!hsl) {
-//         return hslStr;
-//       }
-//       hsl = hsl[0];
-//       hsl = hsl.split(",");
-//       const [h, s, l] = hsl;
-
-//       const hDecimal = parseInt(l) / 100;
-//       const a = (parseInt(s) * Math.min(hDecimal, 1 - hDecimal)) / 100;
-//       const f = (n: number) => {
-//         const k = (n + parseInt(h) / 30) % 12;
-//         const color = hDecimal - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
-
-//         return Math.round(255 * color)
-//           .toString(16)
-//           .padStart(2, "0");
-//       };
-//       return `#${f(0)}${f(8)}${f(4)}`;
-//     }
-
-//     function initPicker() {
-//       picker = Pickr.create({
-//         el: ".color_picker",
-//         theme: "nano",
-//         default: color,
-//         i18n: {
-//           "btn:save": "确定",
-//         },
-//         components: {
-//           preview: true,
-//           opacity: false,
-//           hue: true,
-//           interaction: {
-//             hex: false,
-//             hsla: false,
-//             rgba: false,
-//             input: true,
-//             save: true,
-//           },
-//         },
-//       });
-//       // picker.on("change", (color: any) => {
-//       //   const hexa = color.toHEXA().toString();
-//       //   console.log("setChange", hexa);
-//       // });
-//       picker.on("save", (color: any) => {
-//         picker.hide();
-//         const hexa = color.toHEXA().toString();
-//         emit("change", hexa);
-//       });
-//     }
-//     watch(
-//       () => props.value,
-//       () => {
-//         const color = HSLToHex(props.value);
-//         const res = picker.setColor(color);
-//         console.log("picker change", color, res);
-//       }
-//     );
-//     onMounted(() => {
-//       initPicker();
-//     });
-//     onUnmounted(() => {
-//       if (picker) {
-//         picker.destroyAndRemove();
-//         picker = null;
-//       }
-//     });
-
-//     return () => (
-//       <div
-//         class={ColorPicker}
-//         onClick={() => {
-//           picker?.show();
-//         }}
-//       >
-//         <div class={"color_picker"} id="color_picker"></div>
-//       </div>
-//     );
-//   },
-// });
 export const TextColor = defineComponent({
   props: {
     value: string().def("#666666"),
@@ -227,12 +131,14 @@ export const AlignComp = defineComponent({
 });
 export const LetterSpacingComp = defineComponent({
   props: {
-    value: string().def("0"),
+    value: any<string | number>().def(0),
   },
   emits: ["change"],
   setup(props, { emit }) {
     return () => {
-      const value = parseFloat(props.value) || 0;
+      const value =
+        typeof props.value === "string" ? parseInt(props.value) : props.value;
+
       return (
         <InputNumber
           prefix={<IconTextLetterSpacing class="text-22px mr-6px" />}
@@ -243,10 +149,10 @@ export const LetterSpacingComp = defineComponent({
           value={value}
           onChange={(value: any) => {
             if (!value) {
-              emit("change", "0em");
+              emit("change", "0px");
               return;
             }
-            emit("change", value / 100 + "em");
+            emit("change", value + "px");
           }}
         />
       );
@@ -256,11 +162,13 @@ export const LetterSpacingComp = defineComponent({
 
 export const LineHeightComp = defineComponent({
   props: {
-    value: number().def(1.5),
+    value: any<string | number>().def(1.5),
   },
   emits: ["change"],
   setup(props, { emit }) {
     return () => {
+      const value =
+        typeof props.value === "string" ? parseFloat(props.value) : props.value;
       return (
         <InputNumber
           prefix={<IconTextLineHeight class="text-22px mr-6px" />}
@@ -268,7 +176,7 @@ export const LineHeightComp = defineComponent({
           min={0.5}
           max={3}
           step={0.5}
-          value={props.value || 1.5}
+          value={value || 1.5}
           onChange={(value: any) => {
             if (!value) {
               emit("change", 1.5);
@@ -282,9 +190,6 @@ export const LineHeightComp = defineComponent({
   },
 });
 export const FontStyleWapper = defineComponent({
-  props: {
-    editor: any(),
-  },
   emits: ["change"],
   setup(props, { emit }) {
     const fontStyleColumns = [
@@ -322,11 +227,10 @@ export const FontStyleWapper = defineComponent({
               column={{
                 label: e.label,
                 dataIndex: e.dataIndex,
-                component: (props) => (
-                  <FontStyleComp icon={e.icon} {...props} />
-                ),
+                component: (props) => {
+                  return <FontStyleComp icon={e.icon} {...props} />;
+                },
               }}
-              editor={props.editor}
               onChange={changeVal}
             />
           );
@@ -342,17 +246,15 @@ export const FontStyleComp = defineComponent({
   },
   emits: ["change"],
   setup(props, { emit }) {
-    const triggerStyle = () => {
-      emit("change", !props.value);
-    };
     return () => {
-      console.log(props.value);
       return (
         <Button
           type="text"
           class={props.value ? currStyle : null}
           icon={props.icon}
-          onClick={triggerStyle}
+          onClick={() => {
+            emit("change", !props.value);
+          }}
         ></Button>
       );
     };
@@ -387,7 +289,7 @@ export const FontFamily = defineComponent({
 });
 export const FontSize = defineComponent({
   props: {
-    value: string().def("12px"),
+    value: any().def("12px"),
   },
   emits: ["change"],
   setup(props, { emit }) {
@@ -435,29 +337,41 @@ export const TextToolItem = defineComponent({
   props: {
     column: object<ColumnItem>(),
     index: number(),
-    editor: any(),
     onChange: func(),
   },
   setup(props) {
     const state = reactive({
       value: undefined,
     });
+
+    const { controls } = useEditor();
+    let editor: any = null;
+    watch(
+      () => controls.textEditorCtrl.state.currEditor,
+      () => {
+        editor = toRaw(controls.textEditorCtrl.state.currEditor);
+        initCommands();
+      }
+    );
     function handleValueChange() {
-      const { column, editor } = props;
-      const command = editor ? editor.commands.get(column?.dataIndex) : "";
+      const { column } = props;
+      if (!editor) {
+        return;
+      }
+      const command = editor.commands.get(column?.dataIndex);
       if (command) {
-        console.log("change==>", column?.dataIndex, state.value);
         state.value = command.value;
       }
     }
     const initCommands = () => {
-      const { column, editor } = props;
-      const { controls } = useEditor();
-      const command = editor ? editor.commands.get(column?.dataIndex) : "";
-      console.log(column?.dataIndex, controls.textEditor);
+      const { column } = props;
+      if (!editor) {
+        return;
+      }
+      const command = editor.commands.get(column?.dataIndex);
       if (command) {
+        console.log("init", column?.dataIndex, command.value);
         state.value = command.value;
-
         command.on("change:value", handleValueChange);
       }
     };
@@ -465,8 +379,11 @@ export const TextToolItem = defineComponent({
       initCommands();
     });
     onUnmounted(() => {
-      const { column, editor } = props;
-      const command = editor ? editor.commands.get(column?.dataIndex) : "";
+      const { column } = props;
+      if (!editor) {
+        return;
+      }
+      const command = editor.commands.get(column?.dataIndex);
       if (command) {
         command.off("change:value", handleValueChange);
       }

+ 30 - 41
src/modules/editor/components/CompUI/basicUI/Text/TextToolForm.tsx

@@ -2,9 +2,9 @@ import { useEditor } from "@/modules/editor";
 import { DesignComp } from "@/modules/editor/objects/DesignTemp/DesignComp";
 
 import { css } from "@linaria/core";
-import { defineComponent } from "vue";
+import { defineComponent, toRaw, watch } from "vue";
 import { any } from "vue-types";
-
+import { Divider } from "ant-design-vue";
 import {
   AlignComp,
   FontFamily,
@@ -22,33 +22,34 @@ export const TextToolForm = defineComponent({
   setup(props) {
     const { store, actions, controls } = useEditor();
 
-    const toolbarColumns = [
-      // {
-      //   label: "字体颜色",
-      //   dataIndex: "fontColor",
-      //   component: TextColor,
-      // },
-      // {
-      //   label: "链接",
-      //   dataIndex: "link",
-      //   component: (props: any) => (
-      //     <LinkButton icon={<LinkOutlined />} {...props} />
-      //   ),
-      //   changeExtra: (record: any) => {
-      //     record.value = record.value.value;
-      //     return record;
-      //   },
-      //   itemProps: {
-      //     class: "!mx-2px",
-      //   },
-      // },
-    ];
+    // const toolbarColumns = [
+    // {
+    //   label: "字体颜色",
+    //   dataIndex: "fontColor",
+    //   component: TextColor,
+    // },
+    // {
+    //   label: "链接",
+    //   dataIndex: "link",
+    //   component: (props: any) => (
+    //     <LinkButton icon={<LinkOutlined />} {...props} />
+    //   ),
+    //   changeExtra: (record: any) => {
+    //     record.value = record.value.value;
+    //     return record;
+    //   },
+    //   itemProps: {
+    //     class: "!mx-2px",
+    //   },
+    // },
+    // ];
 
     const changeVal = (e: { dataIndex: string; value: any }) => {
-      const editor = controls.textEditor;
+      let editor = controls.textEditorCtrl.state.currEditor;
       if (!editor) {
         return;
       }
+      editor = toRaw(editor);
       editor.execute(e.dataIndex, e.value);
       console.log("change", e);
       setTimeout(() => {
@@ -59,9 +60,9 @@ export const TextToolForm = defineComponent({
     };
     return () => {
       return (
-        <div id="text_toolbar">
+        <div id="text_toolform">
           <div>文本</div>
-          <div class={"my-18px"}>
+          <div class={"mt-18px"}>
             <div class={formRowItem}>
               <TextToolItem
                 column={{
@@ -71,7 +72,6 @@ export const TextToolForm = defineComponent({
                     class: "w-190px",
                   },
                 }}
-                editor={controls.textEditor}
                 onChange={changeVal}
               />
               <TextToolItem
@@ -83,7 +83,6 @@ export const TextToolForm = defineComponent({
                     class: "!w-full",
                   },
                 }}
-                editor={controls.textEditor}
                 onChange={changeVal}
               />
             </div>
@@ -97,7 +96,6 @@ export const TextToolForm = defineComponent({
                     class: "!w-full",
                   },
                 }}
-                editor={controls.textEditor}
                 onChange={changeVal}
               />
               <TextToolItem
@@ -109,34 +107,25 @@ export const TextToolForm = defineComponent({
                     class: "!w-full",
                   },
                 }}
-                editor={controls.textEditor}
                 onChange={changeVal}
               />
             </div>
             <div class={formRowItem}>
-              <FontStyleWapper
-                editor={controls.textEditor}
-                onChange={changeVal}
-              />
+              <FontStyleWapper onChange={changeVal} />
               <TextToolItem
                 column={{
                   label: "",
                   dataIndex: "alignment",
                   component: AlignComp,
                 }}
-                editor={controls.textEditor}
                 onChange={changeVal}
               />
             </div>
           </div>
-
-          {/* <TextToolUI
-            editor={controls.textEditor}
-            columns={toolbarColumns}
-            onChange={changeVal}
-          /> */}
+          <Divider class={"!my-18px"} />
           <div>填充</div>
           <div>描边</div>
+          <Divider class={"!my-18px"} />
         </div>
       );
     };

+ 0 - 164
src/modules/editor/components/CompUI/basicUI/Text/TextToolUI.tsx

@@ -1,164 +0,0 @@
-import { css } from "@linaria/core";
-import { Tooltip } from "ant-design-vue";
-import { defineComponent, reactive, onMounted, onUnmounted } from "vue";
-import { any, array, func, number, object } from "vue-types";
-
-export interface ColumnItem {
-  label?: string;
-  component?: ((...args: any[]) => any) | Record<string, any>;
-  dataIndex?: string;
-  props?: { [name: string]: any };
-  itemProps?: { [name: string]: any };
-  changeExtra?: (data: any) => any;
-}
-
-export default defineComponent({
-  props: {
-    columns: array<ColumnItem>().isRequired,
-    editor: any(),
-    data: any(),
-    onChange: func(),
-  },
-  setup(props) {
-    return () => <FormUI {...props} />;
-  },
-});
-
-const FormUI = (props: {
-  columns: ColumnItem[];
-  editor: any;
-  onChange?: (...arg: any) => void;
-}) => {
-  const { columns, ...restProps } = props;
-  return (
-    <>
-      {columns?.map((column: ColumnItem, index: number) => {
-        if (!column.dataIndex) {
-          return renderUI({ props: restProps, column, index });
-        }
-        return <RenderFormItem column={column} index={index} {...restProps} />;
-      })}
-    </>
-  );
-};
-
-const renderUI = ({ props, column, index }: any) => {
-  const component = column.component;
-  if (component instanceof Function) {
-    const params: any = {
-      ...props,
-      column,
-      key: index,
-      children: FormUI({ ...props, columns: column.children }),
-    };
-    return component(params);
-  } else {
-    return (
-      <component {...props} column={column} key={index}>
-        <FormUI {...props} columns={column.children} />
-      </component>
-    );
-  }
-};
-
-export const RenderFormItem = defineComponent({
-  props: {
-    column: object<ColumnItem>(),
-    index: number(),
-    editor: any(),
-    onChange: func(),
-    onChangeEnd: func(),
-  },
-  setup(props) {
-    const state = reactive({
-      value: undefined,
-    });
-    function handleValueChange() {
-      const { column, editor } = props;
-      const command = editor ? editor.commands.get(column?.dataIndex) : "";
-      if (command) {
-        console.log("change==>", column?.dataIndex, state.value);
-        state.value = command.value;
-      }
-    }
-    const initCommands = () => {
-      const { column, editor } = props;
-      const command = editor ? editor.commands.get(column?.dataIndex) : "";
-      if (command) {
-        state.value = command.value;
-
-        command.on("change:value", handleValueChange);
-      }
-    };
-    onMounted(() => {
-      initCommands();
-    });
-    onUnmounted(() => {
-      const { column, editor } = props;
-      const command = editor ? editor.commands.get(column?.dataIndex) : "";
-      if (command) {
-        command.off("change:value", handleValueChange);
-      }
-    });
-
-    const changeVal = (value: any, ...args: any[]) => {
-      const { column } = props;
-      let params = {
-        dataIndex: column?.dataIndex,
-        value: { value },
-        ...args,
-      };
-      if (column?.changeExtra) params = column.changeExtra?.(params);
-      props.onChange?.(params);
-      return params;
-    };
-
-    const changeValEnd = (value: any, ...args: any[]) => {
-      const params = changeVal(value, ...args);
-      props.onChangeEnd?.(params);
-    };
-
-    const component = props.column?.component || number;
-    return () => {
-      const { column, index } = props;
-      return (
-        <div
-          key={index}
-          class={formItemStyles}
-          {...column?.itemProps}
-          onClick={(e) => e.stopPropagation()}
-        >
-          {column?.label ? (
-            <Tooltip title={column.label} placement="top">
-              <component
-                value={state.value}
-                {...column.props}
-                onChange={changeVal}
-                onChangeEnd={changeValEnd}
-              />
-            </Tooltip>
-          ) : (
-            <component
-              value={state.value}
-              {...column?.props}
-              onChange={changeVal}
-              onChangeEnd={changeValEnd}
-            />
-          )}
-        </div>
-      );
-    };
-  },
-});
-
-const formItemStyles = css`
-  height: 100%;
-  margin: 0 6px;
-  &.disabled {
-    cursor: not-allowed;
-  }
-`;
-
-export function useFormColumns(columns: ColumnItem[]) {
-  return columns;
-}

+ 4 - 9
src/modules/editor/components/CompUI/basicUI/Text/ckeditor-letter-spacing/LetterSpacingCommand.ts

@@ -14,10 +14,10 @@ export default class LetterSpacingCommand extends Command {
     this.value =
       this.isEnabled && firstBlock?.hasAttribute(Letter_Spacing)
         ? firstBlock.getAttribute(Letter_Spacing)
-        : "1";
+        : "0";
   }
 
-  execute(options: any) {
+  execute(options = {} as any) {
     const editor = this.editor;
     const model = editor.model;
     const doc = model.document;
@@ -34,13 +34,8 @@ export default class LetterSpacingCommand extends Command {
       const currentLetterSpacing = blocks[0].getAttribute(Letter_Spacing);
 
       const removeLetterSpacing =
-        currentLetterSpacing === value || typeof value === "undefined";
-
-      console.log(
-        value,
-        currentLetterSpacing === value,
-        typeof value === "undefined"
-      );
+        /* isDefault( value ) ||  */ currentLetterSpacing === value ||
+        typeof value === "undefined";
 
       if (removeLetterSpacing) {
         removeLetterSpacingFromSelection(blocks, writer);

+ 14 - 11
src/modules/editor/components/CompUI/basicUI/Text/ckeditor-letter-spacing/LetterSpacingEditing.ts

@@ -1,11 +1,15 @@
 import Plugin from "@ckeditor/ckeditor5-core/src/plugin";
-// import { isSupported, buildDefinition } from "./utils";
+import { isSupported, buildDefinition } from "./utils";
 import LetterSpacingCommand from "./LetterSpacingCommand";
 import HeadlessEditor from "../EditorCustom";
 
 export default class LetterSpacingEditing extends Plugin {
   constructor(editor: HeadlessEditor) {
     super(editor);
+
+    editor.config.define("letterSpacing", {
+      options: [0, 1, 2, 3, 4],
+    });
   }
 
   /**
@@ -14,22 +18,21 @@ export default class LetterSpacingEditing extends Plugin {
   init() {
     const editor = this.editor;
     const schema = editor.model.schema;
-
-    // const enabledOptions = editor.config
-    //   .get("lineHeight.options")
-    //   .map((option:any) => String(option))
-    //   .filter(isSupported); // filter
+    const config: any = editor.config?.get("letterSpacing.options");
+    const enabledOptions: any =
+      config &&
+      config?.map((option: any) => String(option)).filter(isSupported); // filter
 
     schema.extend("$block", { allowAttributes: "letterSpacing" });
     editor.model.schema.setAttributeProperties("letterSpacing", {
       isFormatting: true,
     });
 
-    // const definition = buildDefinition(
-    //   enabledOptions /* .filter( option => !isDefault( option ) ) */
-    // );
-
-    // editor.conversion.attributeToAttribute(definition);
+    const definition = buildDefinition(
+      enabledOptions /* .filter( option => !isDefault( option ) ) */
+    );
+    console.log(definition);
+    editor.conversion.attributeToAttribute(definition);
 
     editor.commands.add("letterSpacing", new LetterSpacingCommand(editor));
   }

+ 112 - 0
src/modules/editor/components/CompUI/basicUI/Text/ckeditor-letter-spacing/LetterSpacingUI.ts

@@ -0,0 +1,112 @@
+// import Plugin from "@ckeditor/ckeditor5-core/src/plugin";
+// import Model from "@ckeditor/ckeditor5-ui/src/model";
+// import Collection from "@ckeditor/ckeditor5-utils/src/collection";
+
+// import {
+//   createDropdown,
+//   addListToDropdown,
+// } from "@ckeditor/ckeditor5-ui/src/dropdown/utils";
+
+// import { isSupported, normalizeOptions, optionsKey } from "./utils";
+
+// export default class LetterSpacingUI extends Plugin {
+//   init() {
+//     const editor = this.editor;
+//     const t = editor.t;
+
+//     const options = this._getLocalizedOptions();
+
+//     const command = editor.commands.get("lineHeight");
+
+//     // Register UI component.
+//     editor.ui.componentFactory.add("lineHeight", (locale) => {
+//       const dropdownView = createDropdown(locale);
+//       addListToDropdown(dropdownView, _prepareListOptions(options, command));
+
+//       // Create dropdown model.
+//       dropdownView.buttonView.set({
+//         // label: 'Zeilenhöhe',
+//         label: t("Line Height"),
+//         icon:
+//           editor.config.get("lineHeight.icon") ||
+//           '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"  width="24" height="24" viewBox="0 0 24 24"><path fill="#000000" d="M10,13H22V11H10M10,19H22V17H10M10,7H22V5H10M6,7H8.5L5,3.5L1.5,7H4V17H1.5L5,20.5L8.5,17H6V7Z" /></svg>',
+//         tooltip: true,
+//       });
+
+//       dropdownView.extendTemplate({
+//         attributes: {
+//           class: ["p0thi-ckeditor5-lineHeight-dropdown"],
+//         },
+//       });
+
+//       dropdownView.bind("isEnabled").to(command);
+
+//       // Execute command when an item from the dropdown is selected.
+//       this.listenTo(dropdownView, "execute", (evt) => {
+//         editor.execute(evt.source.commandName, {
+//           value: evt.source.commandParam,
+//         });
+//         editor.editing.view.focus();
+//       });
+
+//       return dropdownView;
+//     });
+//   }
+
+//   _getLocalizedOptions() {
+//     const editor = this.editor;
+//     const t = editor.t;
+
+//     const localizedTitles = {
+//       // Default: 'Standard'
+//       Default: t("Default"),
+//     };
+
+//     const options = normalizeOptions(
+//       editor.config
+//         .get("lineHeight.options")
+//         .filter((option) => isSupported(option))
+//     );
+
+//     return options.map((option: any) => {
+//       const title = localizedTitles[option.title];
+
+//       if (title && title != option.title) {
+//         // Clone the option to avoid altering the original `namedPresets` from `./utils.js`.
+//         option = Object.assign({}, option, { title });
+//       }
+
+//       return option;
+//     });
+//   }
+// }
+
+// function _prepareListOptions(options: optionsKey, command: any) {
+//   const itemDefinitions = new Collection();
+
+//   for (const option of options) {
+//     const def = {
+//       type: "button",
+//       model: new Model({
+//         commandName: "lineHeight",
+//         commandParam: option.model,
+//         label: option.title,
+//         class: "p0thi-ckeditor5-lineHeight-dropdown",
+//         withText: true,
+//       }),
+//     };
+
+//     if (option.view && option.view.classes) {
+//       def.model.set("class", `${def.model.class} ${option.view.classes}`);
+//     }
+
+//     def.model.bind("isOn").to(command, "value", (value) => {
+//       const newValue = value ? parseFloat(value) : value;
+//       return newValue === option.model;
+//     });
+
+//     itemDefinitions.add(def);
+//   }
+
+//   return itemDefinitions;
+// }

+ 66 - 0
src/modules/editor/components/CompUI/basicUI/Text/ckeditor-letter-spacing/utils.ts

@@ -0,0 +1,66 @@
+export function isSupported(option: any) {
+  // return supportedOptions.includes( option );
+  return /^\d(.\d+)?$/gm.test(String(option));
+}
+export type optionsKey = Record<string, any>;
+export function buildDefinition(options: any) {
+  const definition = {
+    model: {
+      key: "letterSpacing",
+      values: options.slice(),
+    },
+    view: {} as optionsKey,
+  };
+
+  for (const option of options) {
+    definition.view[option] = {
+      key: "style",
+      value: {
+        "letter-spacing": option,
+      },
+    };
+  }
+
+  return definition;
+}
+export function normalizeOptions(configuredOptions: any) {
+  return configuredOptions
+    .map(optionDefinition)
+    .filter((option: any) => !!option);
+}
+function optionDefinition(option: any) {
+  if (typeof option === "object") {
+    return option;
+  }
+
+  if (option === "default") {
+    return {
+      model: undefined,
+      title: "Default",
+    };
+  }
+
+  const sizePreset = parseFloat(option);
+
+  if (isNaN(sizePreset)) {
+    return;
+  }
+
+  return generatePixelPreset(sizePreset);
+}
+
+function generatePixelPreset(size: any) {
+  const sizeName = String(size);
+
+  return {
+    title: sizeName,
+    model: size,
+    view: {
+      name: "span",
+      styles: {
+        "letter-spacing": sizeName,
+      },
+      priority: 5,
+    },
+  };
+}

+ 3 - 2
src/modules/editor/components/CompUI/basicUI/Text/component2.tsx

@@ -116,7 +116,7 @@ const EditorComp = defineComponent({
       let curr: any = dom;
       do {
         if (
-          curr.id == "toptoolbar" ||
+          curr.id == "text_toolform" ||
           curr.classList.contains("pcr-app") ||
           curr.classList.contains("editor_toolbar_drop") ||
           curr.classList.contains("ant-select-dropdown")
@@ -173,6 +173,7 @@ const EditorComp = defineComponent({
 
       editorRefVal.model.document.on("change:data", () => {
         const value = editorRefVal?.getData();
+
         if (comp.value !== value) {
           actions.updateCompData(comp, "value", value);
           nextTick(() => {
@@ -198,7 +199,7 @@ const EditorComp = defineComponent({
           });
         }
       });
-      controls.textEditor = editorRefVal;
+      controls.textEditorCtrl.setCurrEditor(editorRefVal);
     };
 
     onMounted(() => {

+ 18 - 16
src/modules/editor/components/CompUI/basicUI/Transfer/select.tsx

@@ -1,8 +1,8 @@
 import { IconRotate , IconMove} from "@/assets/icons";
-import { CompToolbars } from "@/modules/editor/objects/Toolbars";
 import { css } from "@linaria/core";
-import { defineComponent, onMounted, onUnmounted, ref, nextTick, reactive, watch } from "vue";
+import { defineComponent, ref, nextTick, reactive, watch } from "vue";
 import { useEditor } from "../../../..";
+import { LiveToolbars } from "@/modules/editor/objects/Toolbars/liveTools";
 
 
 export const SelectTransfer = defineComponent({
@@ -15,18 +15,11 @@ export const SelectTransfer = defineComponent({
   
     const state = reactive({
        toolbarW: 0,
-       toolbarOpts: [] as any[],
     })
 
     watch(()=>[store.selectId, store.selected], ()=>{
       console.log("changing--")
-      if (store.selected.length == 1) {
-        const comp = store.compMap[store.selected[0]];
-        //@ts-ignore
-        state.toolbarOpts = CompToolbars[comp.compKey] || CompToolbars.default;
-      }  else {
-        state.toolbarOpts = CompToolbars.MultiSelector;
-      }
+   
       nextTick(()=>{
         nextTick(()=>{
           if (!toolbarRef.value) {
@@ -48,7 +41,11 @@ export const SelectTransfer = defineComponent({
 
       const w :any = selectCtrl.objContainer?.getBound();
       const isTextEdit = selectCtrl.selected.length == 1 && selectCtrl.selected[0].comp.compKey == "Text";
-  
+      let yTop = w?.y;
+      if ( yTop < 0) {
+        yTop = 0;
+      }
+
       return (
         <div
           class={[
@@ -59,17 +56,17 @@ export const SelectTransfer = defineComponent({
             top: transferStyle.baseCardTop
           }}
         >
-          {/* <div
+          <div
             id= "toolbar"
             class={toolbarStyle}
             style={{
-              top: w?.y + "px",
+              top: yTop + "px",
               left: (w?.x + w?.width / 2.0 - state.toolbarW / 2.0)  + "px",
             }}
             ref= {toolbarRef}
           >
             {
-              state.toolbarOpts.map((item) => {
+              LiveToolbars.map((item) => {
                 return item.getVisible.call(editor, comp) ? (
                   <item.component
                     class="p-4px"
@@ -79,7 +76,7 @@ export const SelectTransfer = defineComponent({
                 ) : null;
               })
             }
-          </div> */}
+          </div>
 
           <div
             class={["absolute", selctRectStyle]}
@@ -283,8 +280,13 @@ const toolbarStyle = css`
   position: absolute;
   top: 0;
   left: 50%;
-  transform: translate(0%, -60px);
+  transform: translate(0%, -45px);
+  box-shadow: 0px 3px 6px 1px rgba(0,0,0,0.16);
   z-index: 999;
+  color: black;
+  padding: 0 !important;
+  display: flex;
+  align-items: center;
 `;
 
 const resizeHeightBtnCls = css`

+ 4 - 0
src/modules/editor/components/CompUI/basicUI/View.tsx

@@ -52,6 +52,10 @@ export const View = defineComponent({
         });
       }
 
+      if (comp.anim && comp.anim.transition) {
+          style.transition = "all 1s ease-out";
+      }
+
       return (
         <div
           ref={compRef}

+ 31 - 0
src/modules/editor/components/CompUI/defines/align.tsx

@@ -0,0 +1,31 @@
+import { CompAlignTools } from "@/modules/editor/objects/Toolbars/liveTools";
+import { css } from "@linaria/core";
+import { defineComponent, reactive, watchEffect } from "vue";
+
+export default defineComponent({
+  props: {
+
+  },
+  emits: ["change"],
+  setup(props, { emit }) {
+    const state = reactive({
+    });
+
+    return () => {
+      
+      return (
+        <div class={AlignToolsStyle}>
+            {
+                CompAlignTools
+            }
+        </div>
+      );
+    };
+  },
+});
+
+const AlignToolsStyle = css`
+  flex: 1;
+  display: flex;
+  align-items: center;
+`;

+ 2 - 6
src/modules/editor/components/CompUI/defines/createAttrsForm.tsx

@@ -7,16 +7,12 @@ import { Size } from "../formItems/Size";
 import Slider from "../formItems/Slider";
 import { createColorOpts } from "./formOpts/createColorOpts";
 import { Divider } from "ant-design-vue";
-import { GroupNumber } from "../formItems/GroupNumber";
 
 export const layoutColumns: ColumnItem[] = [
   {
-    // label: "尺寸",
+    label: "尺寸",
     dataIndex: "layout.size",
     component: Size,
-    props: {
-      labels: ["宽度", "高度"],
-    },
   },
   // {
   //   label: "对齐",
@@ -236,7 +232,7 @@ export function createAttrsForm(valueColumns: ColumnItem[], columnsUI?: any) {
                 <Divider></Divider>
               </>
             ) : null}
-            {columnsUI && <columnsUI component={component}/>}
+            {columnsUI && <columnsUI component={component} />}
             <div>布局</div>
             <FormUI
               data={component}

+ 129 - 55
src/modules/editor/components/CompUI/formItems/Size.tsx

@@ -1,92 +1,166 @@
+import { IconHeight, IconWidth } from "@/assets/icons";
 import { CompSizeOpts } from "@/modules/editor/objects/DesignTemp/creates/CompSize";
+import { Layout } from "@/modules/editor/typings";
+import { css } from "@linaria/core";
 import { InputNumber, Select } from "ant-design-vue";
-import { defineComponent } from "vue";
+import { AnyFun } from "queenjs/typing";
+import { defineComponent, reactive } from "vue";
 import { any } from "vue-types";
+import { TipIcons } from "../../TipIcons";
 
 const selectOptions = [
-  { value: "px", label: "像素", options: { step: 1 } },
-  { value: "%", label: "比例", options: { step: 0.1, max: 100, min: 0 } },
+  { value: "px", label: "PX", options: { step: 1 } },
+  { value: "%", label: "%", options: { step: 0.1 } },
 ];
 
 export const Size = defineComponent({
   props: {
-    value: any<[number, number, string?, string?]>().def([0, 0]),
+    value: any<Layout["size"]>().def([0, 0]),
   },
   emits: ["change"],
   setup(props, { emit }) {
     const CompSizeOptsList = [CompSizeOpts.w, CompSizeOpts.h];
+    const state = reactive({
+      relateRatio: 0,
+    });
 
-    function changeVal(unit: any, index: number, v: any) {
+    function changeVal(index: number, v: any) {
       const { value } = props;
+      const unit = value[2]?.unit;
       value[index] = parseFloat(v) || 0;
+
       if (unit === "%") {
         value[index] = CompSizeOptsList[index].getPxSize(
           value[index] as number
         );
       }
+
+      if (state.relateRatio) {
+        const isChangeW = index === 0;
+        if (isChangeW) {
+          value[1] = value[0] / state.relateRatio;
+        } else {
+          value[0] = value[1] * state.relateRatio;
+        }
+      }
+
       emit("change", value);
     }
 
-    function changeUnit(index: number, unit: any) {
+    function changeUnit(unit: any) {
       const { value } = props;
-      value[index + 2] = unit;
+      if (!value[2]?.unit) {
+        value[2] = { unit };
+      } else {
+        value[2].unit = unit;
+      }
       emit("change", value);
     }
 
-    function fmtVal(val: number, unit: string, index: number) {
+    function changeRelate() {
+      state.relateRatio = !state.relateRatio
+        ? props.value[0] / props.value[1]
+        : 0;
+    }
+
+    function fmtVal(index: number) {
+      const unit = props.value[2]?.unit;
+      const val = props.value[index] as number;
       switch (unit) {
-        case "px":
-          return val.toFixed(0);
         case "%":
-          return CompSizeOptsList[index].getVSize(val).toFixed(1);
+          return CompSizeOptsList[index].getVSize(val).toFixed(0);
         default:
-          return "";
+          return val.toFixed(0);
       }
     }
 
-    return () => {
-      const values = props.value.slice(0, 2) as number[];
-      const units = props.value.slice(2) as string[];
-
-      return (
-        <div class="flex space-x-10px">
-          {values.map((value, i) => {
-            const unit = units[i] || selectOptions[0].value;
-            const inputOpts =
-              selectOptions.find((d) => d.value === unit)?.options || {};
-            return (
-              <InputNumber
-                key={i + unit}
-                value={fmtVal(value as number, unit, i)}
-                onChange={changeVal.bind(null, unit, i)}
-                {...inputOpts}
-              >
-                {{
-                  addonBefore() {
-                    return (
-                      <span class="-mx-8px">
-                        {CompSizeOptsList[i].label}
-                        <Select
-                          value={unit}
-                          onChange={changeUnit.bind(null, i)}
-                        >
-                          {selectOptions.map((d) => {
-                            return (
-                              <Select.Option key={d.value}>
-                                {d.value === "%" ? CompSizeOptsList[i].vUnit : d.value}
-                              </Select.Option>
-                            );
-                          })}
-                        </Select>
-                      </span>
-                    );
-                  },
-                }}
-              </InputNumber>
-            );
-          })}
+    return () => (
+      <div class="space-y-10px flex-1">
+        <div class="flex justify-between">
+          <SizeInput
+            label="X"
+            icon={IconWidth}
+            value={fmtVal(0)}
+            onChange={(v) => changeVal(0, v)}
+          />
+          <TipIcons.Relate
+            class={[relateIconCls, state.relateRatio && "active"]}
+            onClick={changeRelate}
+          />
         </div>
-      );
-    };
+        <div class="flex justify-between">
+          <SizeInput
+            label="Y"
+            icon={IconHeight}
+            value={fmtVal(1)}
+            onChange={(v) => changeVal(1, v)}
+          />
+          <Select
+            class={selUnitCls}
+            bordered={false}
+            value={props.value[2]?.unit || selectOptions[0].value}
+            onChange={(v) => changeUnit(v)}
+          >
+            {selectOptions.map((d) => {
+              return <Select.Option key={d.value}>{d.label}</Select.Option>;
+            })}
+          </Select>
+        </div>
+      </div>
+    );
   },
 });
+
+const SizeInput = (props: {
+  label: string;
+  icon: any;
+  value: string;
+  onChange: AnyFun;
+}) => {
+  const { label, icon, ...inputProps } = props;
+  return (
+    <div class={numberInputCls}>
+      <span class="pl-14px pr-1px text-14px">{label}</span>
+      <InputNumber class="flex-1" bordered={false} {...inputProps} />
+      <icon class="tipIcon" />
+    </div>
+  );
+};
+
+const numberInputCls = css`
+  @apply inline-flex items-center flex-1 w-0 mr-12px;
+  background-color: #303030;
+  border-radius: 4px;
+  overflow: hidden;
+
+  .tipIcon {
+    font-size: 24px;
+    padding: 3px 5px;
+    background-color: #373737;
+  }
+`;
+
+const relateIconCls = css`
+  padding: 3px 17px;
+  font-size: 24px;
+  border-radius: 4px;
+  background-color: #303030;
+  cursor: pointer;
+
+  &.active {
+    background-color: rgba(234, 158, 64, 0.2);
+    color: #ea9e40;
+  }
+`;
+
+const selUnitCls = css`
+  width: 58px;
+  height: 30px;
+  border-radius: 4px;
+  background-color: #303030;
+  cursor: pointer;
+
+  .ant-select-selector {
+    padding: 0 8px;
+  }
+`;

+ 12 - 10
src/modules/editor/components/TipIcons/index.ts

@@ -25,11 +25,12 @@ import {
   IconAlignYBottom,
   IconWidth,
   IconHeight,
+  IconDelete,
+  IconRelate,
 } from "@/assets/icons";
 import {
   IconCamera,
   IconCube,
-  IconDelete,
   IconEdit,
   IconEyeOff,
   IconEyeOn,
@@ -41,9 +42,6 @@ import {
 import { createTipIcon } from "./create";
 import { FontSize } from "./TipIcon";
 
-
-
-
 export const TipIcons = {
   Rename: createTipIcon({
     icons: [IconEdit],
@@ -69,7 +67,7 @@ export const TipIcons = {
     icons: [IconEdit],
     tips: ["编辑"],
   }),
-  
+
   Position: createTipIcon({
     icons: [IconFloatOff, IconFloatOn],
     tips: ["开启浮动", "关闭浮动"],
@@ -83,7 +81,7 @@ export const TipIcons = {
     tips: ["锁定", "未锁定"],
   }),
   Delete: createTipIcon({
-    icons: [IconDelete],
+    icons: [FontSize(IconDelete, 26)],
     tips: ["删除"],
   }),
   Copy: createTipIcon({
@@ -107,11 +105,11 @@ export const TipIcons = {
     tips: ["重做(Ctrl+Shift+Z)"],
   }),
   LayerUp: createTipIcon({
-    icons: [IconLayerUp],
+    icons: [FontSize(IconLayerUp, 26)],
     tips: ["层级上移"],
   }),
   LayerDown: createTipIcon({
-    icons: [IconLayerDown],
+    icons: [FontSize(IconLayerDown, 26)],
     tips: ["层级下移"],
   }),
   ParentComp: createTipIcon({
@@ -139,11 +137,11 @@ export const TipIcons = {
     tips: ["确定"],
   }),
   Cropper: createTipIcon({
-    icons: [IconCroperr],
+    icons: [FontSize(IconCroperr, 26)],
     tips: ["裁剪"],
   }),
   AlignXLeft: createTipIcon({
-    icons: [FontSize(IconAlignXLeft,28)],
+    icons: [FontSize(IconAlignXLeft, 28)],
     tips: ["左对齐"],
   }),
   AlignXCenter: createTipIcon({
@@ -182,4 +180,8 @@ export const TipIcons = {
     icons: [FontSize(IconHeight, 28)],
     tips: ["相同高度"],
   }),
+  Relate: createTipIcon({
+    icons: [IconRelate],
+    tips: ["锁定宽高比"],
+  }),
 };

+ 0 - 2
src/modules/editor/components/index.ts

@@ -1,9 +1,7 @@
 import Preview from "./Preview";
-import Viewport from "./Viewport";
 import CompSave from "./CompSave";
 
 export default {
-  Viewport,
   Preview,
   CompSave,
 };

+ 66 - 0
src/modules/editor/controllers/AnimCtrl/index.ts

@@ -0,0 +1,66 @@
+import { Effect, ModuleControl } from "queenjs";
+import { EditorModule } from "../../module";
+import { DesignComp } from "../../objects/DesignTemp/DesignComp";
+import { Matrix } from "../SelectCtrl/matrix";
+
+
+export class AnimCtrl extends ModuleControl<EditorModule> {
+
+  initEvent() {
+     Effect.value(()=>this.store.shortPage).item((v)=>v.offset, (shortState)=>{
+        console.log("xx")
+
+        let next = shortState.index;
+        if (shortState.offset < 0 ) {
+            next = shortState.index + 1;
+        }
+        if (shortState.offset > 0 ) {
+            next = shortState.index - 1;
+        }
+        this.initAnim();
+        this.startAnim(next);
+
+     }).run();
+  }
+
+  startAnim(index:number) {
+    const childrens = this.helper.findCardAllChildren(index);
+
+    console.log("start anim=>", index, childrens.length);
+
+    childrens.forEach((c)=>{
+        const comp = this.helper.findComp(c) as DesignComp;
+        if (!comp.anim) return;
+        comp.anim.transition = false;
+        comp.layout.transformMatrix = comp.anim.startMatrix;
+        comp.layout.opacity = 0;
+
+        setTimeout(() => {
+            if (comp.anim) {
+                comp.anim.transition = true;
+                comp.layout.transformMatrix = comp.anim.endMatrix;
+                comp.layout.opacity = 1;
+            }
+        }, 100);
+    })
+  }
+  inited = false;
+  initAnim() {
+    if (this.inited) return;
+    this.inited = true;
+
+    let n = this.store.streamCardIds.length;
+    for( let i=0; i<n; i++) {
+        const childrens = this.helper.findCardAllChildren(i);
+        childrens.forEach((c)=>{
+            const comp = this.helper.findComp(c) as DesignComp;
+            const end = comp.layout.transformMatrix || "matrix(1,0,0,1,0,0)";
+            const m = Matrix.createFromMatrixStr(end);
+            m.ty = m.ty - comp.getH();
+            m.tx = m.tx - comp.getW();
+
+            comp.anim = {transition:false, startMatrix: m.getMatrixStr(), endMatrix: end}
+        })
+    }
+  }
+}

+ 15 - 0
src/modules/editor/controllers/TextEditorCtrl/index.ts

@@ -0,0 +1,15 @@
+import { ModuleControl } from "queenjs";
+import { reactive } from "vue";
+import { EditorModule } from "../../module";
+
+export class TextEditorCtrl extends ModuleControl<EditorModule> {
+  state = reactive({
+    currEditor: null as any,
+  });
+  constructor(moduel: EditorModule) {
+    super(moduel);
+  }
+  setCurrEditor(editor: any) {
+    this.state.currEditor = editor;
+  }
+}

+ 21 - 4
src/modules/editor/module/actions/edit.tsx

@@ -638,10 +638,27 @@ export const editActions = EditorModule.action({
   },
   // 设置组件层级
   setCompLayer(comp: DesignComp, offset: number) {
-    comp.layout.zIndex = Math.min(
-      Math.max((comp.layout.zIndex || 0) + offset, 0),
-      99
-    );
+    const cards = (this.store.currStreamCard.children.default || []);
+    const i = cards.indexOf(comp.id);
+    if (i == -1) return;
+
+    if (offset < 0) {//向下移动
+       if (i== 0) return;
+      const temp = cards[i-1];
+      cards[i-1] = comp.id;
+      cards[i] = temp;
+      return;
+    }
+    
+    if (i == cards.length -1) return;
+    const temp = cards[i+1];
+    cards[i+1] = comp.id;
+    cards[i] = temp;
+
+    // comp.layout.zIndex = Math.min(
+    //   Math.max((comp.layout.zIndex || 0) + offset, 0),
+    //   99
+    // );
   },
   //横向对齐
   setAlignX(flag: 0 | 1 | 2 | 3) {

+ 5 - 0
src/modules/editor/module/helpers/index.ts

@@ -71,6 +71,11 @@ export const helpers = EditorModule.helper({
     return this.store.designData.compMap["root"];
   },
 
+  findCardAllChildren(index:number) {
+    const cardId = this.store.streamCardIds[index];
+    return this.store.designData.compMap[cardId].children.default || [] as string[];
+  },
+
   getCompCard(compId: string) {
     const paths: DesignComp[] = this.helper.getCompTrees(compId);
     return paths[1];

+ 5 - 1
src/modules/editor/module/index.ts

@@ -22,6 +22,8 @@ import { manualActions } from "./actions/editWithManualHistory";
 import { wxController } from "@/controllers/wxController";
 import { ImageCropperCtrl } from "../controllers/CropperCtrl";
 import { MediaCtrl } from "../controllers/MediaCtrl/indext";
+import { AnimCtrl } from "../controllers/AnimCtrl";
+import { TextEditorCtrl } from "../controllers/TextEditorCtrl";
 
 export class EditorModule extends ModuleRoot {
   config = this.setConfig({
@@ -62,12 +64,14 @@ export class EditorModule extends ModuleRoot {
     selectCtrl: new SelectCtrl(this),
     cropCtrl: new ImageCropperCtrl(this),
     mediaCtrl: new MediaCtrl(this),
-    textEditor: null as any,
+    textEditorCtrl: new TextEditorCtrl(this),
+    animCtrl: new AnimCtrl(this)
   };
   compObjsMap = new Map<string, CompObject>();
 
   onReady() {
     this.actions.init();
+    this.controls.animCtrl.initEvent();
   }
 
   jumpIndexHtml(route = "#/") {

+ 2 - 0
src/modules/editor/objects/DesignTemp/DesignComp.ts

@@ -14,6 +14,8 @@ export class DesignComp {
   layout: Layout = { size: [200, 200] };
   background: Background = {};
   children: Record<string, any> & { default?: string[] } = {};
+  anim?:{startMatrix: string, endMatrix:string, transition: boolean}
+
   constructor(data?: Partial<DesignComp>) {
     if (!data) return;
     if (data instanceof DesignComp) return data;

+ 2 - 2
src/modules/editor/objects/DesignTemp/creates/createCompStyle.ts

@@ -78,12 +78,12 @@ export function createCompStyle(
   }
 
   if (layout.size) {
-    const [w, h, wUnit, hUnit] = layout.size;
+    const [w, h, sizeOpts] = layout.size;
     if (w) {
       style.width = designToNaturalSize(w);
     }
     if (h) {
-      style.height = designToNaturalSize(h, { adaptiveH: hUnit === "%" });
+      style.height = designToNaturalSize(h, { adaptiveH: sizeOpts?.unit === "%" });
     }
   }
 

+ 7 - 3
src/modules/editor/objects/Toolbars/default.ts

@@ -119,9 +119,13 @@ export const toolbars = createToolbars({
   delete: {
     component: TipIcons.Delete,
     getVisible(comp) {
-      return this.helper.isCompCanDelete(comp.id);
+      return  this.store.selected.length > 1 || (!!comp && this.helper.isCompCanDelete(comp.id));
     },
     onClick(comp) {
+      if (this.store.selected.length > 1) {
+        this.actions.removeSelectComps();
+        return;
+      }
       this.actions.removeComp(comp.id);
     },
   },
@@ -206,7 +210,7 @@ export const toolbars = createToolbars({
   // 定位图层上移
   layerUp: {
     component: TipIcons.LayerUp,
-    getVisible: (comp) => true,
+    getVisible: (comp) => !!comp,
     onClick(comp) {
       this.actions.setCompLayer(comp, 1);
     },
@@ -214,7 +218,7 @@ export const toolbars = createToolbars({
   // 定位图层下移
   layerDown: {
     component: TipIcons.LayerDown,
-    getVisible: (comp) => true,
+    getVisible: (comp) => !!comp,
     onClick(comp) {
       this.actions.setCompLayer(comp, -1);
     },

+ 21 - 0
src/modules/editor/objects/Toolbars/liveTools.ts

@@ -0,0 +1,21 @@
+import { ToolbarItem, toolbars } from "./default";
+import { LayoutToolbars } from "./layout";
+
+export const LiveToolbars: ToolbarItem[] = [
+    toolbars.imageCropper,
+    toolbars.layerUp,
+    toolbars.layerDown,
+    toolbars.createGroup,
+    toolbars.cancelGroup,
+    toolbars.delete
+]
+
+export const CompAlignTools:ToolbarItem[] = [
+    LayoutToolbars.xLeft,
+    LayoutToolbars.xCenter,
+    LayoutToolbars.xRight,
+
+    LayoutToolbars.YTop,
+    LayoutToolbars.YCenter,
+    LayoutToolbars.YBottom
+]

+ 3 - 2
src/modules/editor/typings.ts

@@ -2,12 +2,13 @@ import { CompUI } from "./components/CompUI";
 
 export type ICompKeys = keyof typeof CompUI;
 
-export type EditorMode = "editPage" | "editComp" | "preview" | "display"
+export type EditorMode = "editPage" | "editComp" | "preview" | "display";
 
 export type Layout = {
   position?: "absolute";
   visible?: boolean;
-  size: [number, number, string?, string?]; // width height wUnit hUnit
+  size: [number, number, { unit?: "px" | "%" }?]; // width height wUnit hUnit
+  direction?: "top" | "bottom"; // 默认top
   mask?: string;
   alignSelf?: string;
   transform?: {

+ 2 - 1
src/pages/editor/EditPage/index.tsx

@@ -1,4 +1,5 @@
 import { initEditor } from "@/modules/editor";
+import Viewport from "@/modules/editor/components/Viewport";
 import { EditorMode } from "@/modules/editor/typings";
 import { useResource } from "@/modules/resource";
 import { SelectOneImage } from "@/pages/website/Material2/modal";
@@ -41,5 +42,5 @@ export default defineComponent(() => {
     return resource.treeController.selectOnePackScene();
   };
 
-  return () => <editor.components.Viewport class="!h-100vh" />;
+  return () => <Viewport class="!h-100vh" />;
 });