Browse Source

Merge branch 'dev' of http://124.70.149.18:10880/lianghj/queenshow into dev

bianjiang 1 year ago
parent
commit
9645a410aa

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

@@ -1,3 +1,3 @@
 
 import { createIcon } from '@queenjs/icons';
-export const IconGroup = createIcon(<svg viewBox="0 0 34 34"><g transform="translate(-983 -379)"><rect fill="none" width="34" height="34" rx="6" transform="translate(983 379)" /><g transform="translate(991.428 387.423)"><g transform="translate(0)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.835,6H6V8.881" transform="translate(-6 -6)" /><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.855,28.861H6V26.012" transform="translate(-6 -11.716)" /><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M26,6h2.856V8.868" transform="translate(-11.714 -6)" /><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M16.028,6h2.843" transform="translate(-8.865 -6)" /><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M6,16v2.857" transform="translate(-6 -8.856)" /><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M30,16v1.8" transform="translate(-12.855 -8.856)" /><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M15.992,30h2.4" transform="translate(-8.854 -12.855)" /></g><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M17.205,12.971h-5" transform="translate(0 1.674)" /><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M17.205,12.971h-5" transform="translate(27.676 -0.061) rotate(90)" /></g></g></svg>)
+export const IconGroup = createIcon(<svg viewBox="0 0 34 34"><g transform="translate(-983 -379)"><rect fill="none" width="34" height="34" rx="6" transform="translate(983 379)"/><g transform="translate(991.428 387.423)"><g transform="translate(0)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.835,6H6V8.881" transform="translate(-6 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.855,28.861H6V26.012" transform="translate(-6 -11.716)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M26,6h2.856V8.868" transform="translate(-11.714 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M16.028,6h2.843" transform="translate(-8.865 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M6,16v2.857" transform="translate(-6 -8.856)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M30,16v1.8" transform="translate(-12.855 -8.856)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M15.992,30h2.4" transform="translate(-8.854 -12.855)"/></g><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M17.205,12.971h-5" transform="translate(0 1.674)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M17.205,12.971h-5" transform="translate(27.676 -0.061) rotate(90)"/></g></g></svg>)

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

@@ -0,0 +1,3 @@
+
+import { createIcon } from '@queenjs/icons';
+export const IconHeight = createIcon(<svg viewBox="0 0 34 34"><g transform="translate(-8814 7759)"><g transform="translate(8814 -7759)"><rect fill="none" width="34" height="34"/></g><g transform="translate(8846.416 -7756.912) rotate(90)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M6,7H23.824"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M8,24H23.843" transform="translate(-1.01 -8.583)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M10.28,22.567,8,20.285,10.283,18" transform="translate(-1.01 -4.867)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8,22.567l2.28-2.282L8,18" transform="translate(12.55 -4.867)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M6,41H23.824" transform="translate(0 -17.167)"/></g></g></svg>)

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

@@ -0,0 +1,3 @@
+
+import { createIcon } from '@queenjs/icons';
+export const IconWidth = createIcon(<svg viewBox="0 0 34 34"><g transform="translate(-8814 7759)"><g transform="translate(8814 -7759)"><rect fill="none" width="34" height="34"/></g><g transform="translate(8816.088 -7757.417)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M6,7H23.824"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M8,24H23.843" transform="translate(-1.01 -8.583)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M10.28,22.567,8,20.285,10.283,18" transform="translate(-1.01 -4.867)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8,22.567l2.28-2.282L8,18" transform="translate(12.55 -4.867)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M6,41H23.824" transform="translate(0 -17.167)"/></g></g></svg>)

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

@@ -24,6 +24,7 @@ export * from "./components/IconEmpty";
 export * from "./components/IconFloatOff";
 export * from "./components/IconFloatOn";
 export * from "./components/IconGroup";
+export * from "./components/IconHeight";
 export * from "./components/IconImage";
 export * from "./components/IconLayerDown";
 export * from "./components/IconLayers";
@@ -57,3 +58,4 @@ export * from "./components/IconTransfer";
 export * from "./components/IconUngroup";
 export * from "./components/IconVideo";
 export * from "./components/IconWechat";
+export * from "./components/IconWidth";

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

@@ -1 +1 @@
-<svg viewBox="0 0 34 34"><g transform="translate(-983 -379)"><rect fill="none" width="34" height="34" rx="6" transform="translate(983 379)"/><g transform="translate(991.428 387.423)"><g transform="translate(0)"><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.835,6H6V8.881" transform="translate(-6 -6)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.855,28.861H6V26.012" transform="translate(-6 -11.716)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M26,6h2.856V8.868" transform="translate(-11.714 -6)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M16.028,6h2.843" transform="translate(-8.865 -6)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M6,16v2.857" transform="translate(-6 -8.856)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M30,16v1.8" transform="translate(-12.855 -8.856)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" d="M15.992,30h2.4" transform="translate(-8.854 -12.855)"/></g><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" d="M17.205,12.971h-5" transform="translate(0 1.674)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" d="M17.205,12.971h-5" transform="translate(27.676 -0.061) rotate(90)"/></g></g></svg>
+<svg viewBox="0 0 34 34"><g transform="translate(-983 -379)"><rect fill="none" width="34" height="34" rx="6" transform="translate(983 379)"/><g transform="translate(991.428 387.423)"><g transform="translate(0)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.835,6H6V8.881" transform="translate(-6 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.855,28.861H6V26.012" transform="translate(-6 -11.716)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M26,6h2.856V8.868" transform="translate(-11.714 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M16.028,6h2.843" transform="translate(-8.865 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M6,16v2.857" transform="translate(-6 -8.856)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M30,16v1.8" transform="translate(-12.855 -8.856)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M15.992,30h2.4" transform="translate(-8.854 -12.855)"/></g><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M17.205,12.971h-5" transform="translate(0 1.674)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M17.205,12.971h-5" transform="translate(27.676 -0.061) rotate(90)"/></g></g></svg>

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

@@ -0,0 +1 @@
+<svg viewBox="0 0 34 34"><g transform="translate(-8814 7759)"><g transform="translate(8814 -7759)"><rect fill="none" width="34" height="34"/></g><g transform="translate(8846.416 -7756.912) rotate(90)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M6,7H23.824"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M8,24H23.843" transform="translate(-1.01 -8.583)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M10.28,22.567,8,20.285,10.283,18" transform="translate(-1.01 -4.867)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8,22.567l2.28-2.282L8,18" transform="translate(12.55 -4.867)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M6,41H23.824" transform="translate(0 -17.167)"/></g></g></svg>

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

@@ -1 +1 @@
-<svg viewBox="0 0 34 34"><g transform="translate(-983 -379)"><rect fill="none" width="34" height="34" rx="6" transform="translate(983 379)"/><g transform="translate(991.428 387.423)"><g transform="translate(0)"><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.835,6H6V8.881" transform="translate(-6 -6)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.855,28.861H6V26.012" transform="translate(-6 -11.716)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M26,6h2.856V8.868" transform="translate(-11.714 -6)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M16.028,6h2.843" transform="translate(-8.865 -6)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M6,16v2.857" transform="translate(-6 -8.856)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M30,16v1.8" transform="translate(-12.855 -8.856)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" d="M15.992,30h2.4" transform="translate(-8.854 -12.855)"/></g><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" d="M5.7,0H0" transform="translate(13.116 13.115) rotate(45)"/><path fill="none" stroke="#111" stroke-linecap="round" stroke-width="1.2px" d="M5.7,0H0" transform="translate(17.145 13.115) rotate(135)"/></g></g></svg>
+<svg viewBox="0 0 34 34"><g transform="translate(-983 -379)"><rect fill="none" width="34" height="34" rx="6" transform="translate(983 379)"/><g transform="translate(991.428 387.423)"><g transform="translate(0)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.835,6H6V8.881" transform="translate(-6 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8.855,28.861H6V26.012" transform="translate(-6 -11.716)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M26,6h2.856V8.868" transform="translate(-11.714 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M16.028,6h2.843" transform="translate(-8.865 -6)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M6,16v2.857" transform="translate(-6 -8.856)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M30,16v1.8" transform="translate(-12.855 -8.856)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M15.992,30h2.4" transform="translate(-8.854 -12.855)"/></g><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M5.7,0H0" transform="translate(13.116 13.115) rotate(45)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M5.7,0H0" transform="translate(17.145 13.115) rotate(135)"/></g></g></svg>

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

@@ -0,0 +1 @@
+<svg viewBox="0 0 34 34"><g transform="translate(-8814 7759)"><g transform="translate(8814 -7759)"><rect fill="none" width="34" height="34"/></g><g transform="translate(8816.088 -7757.417)"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M6,7H23.824"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M8,24H23.843" transform="translate(-1.01 -8.583)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M10.28,22.567,8,20.285,10.283,18" transform="translate(-1.01 -4.867)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" stroke-linejoin="round" d="M8,22.567l2.28-2.282L8,18" transform="translate(12.55 -4.867)"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.2px" d="M6,41H23.824" transform="translate(0 -17.167)"/></g></g></svg>

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

@@ -212,8 +212,8 @@ const borderContentStyle = css`
 
 const resizeStyle = css`
   position: absolute;
-  width: 16px;
-  height: 16px;
+  width: 10px;
+  height: 10px;
   border-radius: 50%;
   background-color: #fff;
   z-index: 999;

+ 14 - 0
src/modules/editor/components/TipIcons/index.ts

@@ -23,6 +23,8 @@ import {
   IconAlginYCenter,
   IconAlignYBetween,
   IconAlignYBottom,
+  IconWidth,
+  IconHeight,
 } from "@/assets/icons";
 import {
   IconCamera,
@@ -80,6 +82,10 @@ export const TipIcons = {
     icons: [IconDelete],
     tips: ["删除"],
   }),
+  Copy: createTipIcon({
+    icons: [IconCamera],
+    tips: ["拷贝"],
+  }),
   FullWidth: createTipIcon({
     icons: [IconCube],
     tips: ["全屏宽度"],
@@ -164,4 +170,12 @@ export const TipIcons = {
     icons: [FontSize(IconAlignYBetween, 28)],
     tips: ["纵向均匀排布"],
   }),
+  SameWidth: createTipIcon({
+    icons: [FontSize(IconWidth, 28)],
+    tips: ["相同宽度"],
+  }),
+  SameHeight: createTipIcon({
+    icons: [FontSize(IconHeight, 28)],
+    tips: ["相同高度"],
+  }),
 };

+ 67 - 50
src/modules/editor/components/Viewport/Slider/SliderLeft/Sources.tsx

@@ -8,6 +8,7 @@ import { useResource } from "@/modules/resource";
 import { Loadmore } from "@queenjs/ui";
 import { queenApi } from "queenjs";
 import SourceItem from "./SourceItem";
+import { Button } from "ant-design-vue";
 
 export const Sources = defineComponent({
   props: {
@@ -57,57 +58,73 @@ export const Sources = defineComponent({
       const { sourceType } = props;
 
       return (
-        <div>
-          <Container
-            class="grid grid-cols-2 gap-10px"
-            behaviour="copy"
-            group-name="canvas"
-            animation-duration={0}
-            get-child-payload={(index: number) => {
-              return {
-                type: props.sourceType,
-                data: dataSource[index],
-              };
-            }}
-          >
-            {dataSource.map((item: any) => (
-              <Draggable>
-                <SourceItem
-                  class="draggable-item cursor-pointer"
-                  record={item}
-                  isVideo={sourceType == "Video"}
-                  tagable={props.sourceFrom == "user"}
-                  onClick={() => clickToDesign(item.file.url)}
-                  onMenu={async (name) => {
-                    console.log(name);
-                    if (name == "delete") {
-                      await resource.actions.deleteMaterial(item);
-                      control.fresh();
-                      queenApi.messageSuccess("删除成功!");
-                      return;
-                    }
+        <div class={[ props.sourceFrom == "user" && "flex flex-col !px-0"]}>
+          {
+            props.sourceFrom == "user" &&   <Button
+                class="mt-12px mb-12px"
+                block
+                type="primary"
+                onClick={async () => {
+                  await resource.actions.createMaterial()
+                  control.fresh();
+                }}
+              >
+                上传素材
+              </Button>
+          }
 
-                    if (name == "publish" || name == "unpublish") {
-                      const pub = name == "publish";
-                      await resource.actions.publishMaterial(item, pub);
-                      item.published = pub;
-                      queenApi.messageSuccess("操作成功!");
-                    }
-                  }}
-                />
-              </Draggable>
-            ))}
-          </Container>
-          {dataSource.length == 0 ? (
-            <Empty class="pt-150px" />
-          ) : (
-            <Loadmore
-              class="mt-20px"
-              loading={control.state.loading}
-              canLoad={control.state.canLoadNext}
-              onChange={control.loadNextPage}
-            />
-          )}
+          <div class={[ props.sourceFrom == "user" && "flex-grow overflow-x-hidden overflow-y-auto scrollbar"]}>
+            <Container
+              class="grid grid-cols-2 gap-10px"
+              behaviour="copy"
+              group-name="canvas"
+              animation-duration={0}
+              get-child-payload={(index: number) => {
+                return {
+                  type: props.sourceType,
+                  data: dataSource[index],
+                };
+              }}
+            >
+              {dataSource.map((item: any) => (
+                <Draggable>
+                  <SourceItem
+                    class="draggable-item cursor-pointer"
+                    record={item}
+                    isVideo={sourceType == "Video"}
+                    tagable={props.sourceFrom == "user"}
+                    onClick={() => clickToDesign(item.file.url)}
+                    onMenu={async (name) => {
+                      console.log(name);
+                      if (name == "delete") {
+                        await resource.actions.deleteMaterial(item);
+                        control.fresh();
+                        queenApi.messageSuccess("删除成功!");
+                        return;
+                      }
+
+                      if (name == "publish" || name == "unpublish") {
+                        const pub = name == "publish";
+                        await resource.actions.publishMaterial(item, pub);
+                        item.published = pub;
+                        queenApi.messageSuccess("操作成功!");
+                      }
+                    }}
+                  />
+                </Draggable>
+              ))}
+            </Container>
+            {dataSource.length == 0 ? (
+              <Empty class="pt-150px" />
+            ) : (
+              <Loadmore
+                class="mt-20px"
+                loading={control.state.loading}
+                canLoad={control.state.canLoadNext}
+                onChange={control.loadNextPage}
+              />
+            )}
+          </div>
         </div>
       );
     };

+ 1 - 1
src/modules/editor/components/Viewport/Slider/SliderLeft/Templates/index.tsx

@@ -65,7 +65,7 @@ export default defineUI({
                       src={item.thumbnail}
                       size={240}
                     />
-                    <div class="absolute w-1/1 h-1/1 top-0 left-0 bg-dark-500 bg-opacity-20 transition opacity-0 hover:(opacity-100) text-dark-500">
+                    <div class="absolute w-1/1 h-1/1 top-0 left-0 bg-dark-900 bg-opacity-30 transition opacity-0 hover:(opacity-100) text-dark-500">
                       <IconPreview
                         class="absolute right-6px top-6px text-22px bg-light-50 rounded-2px cursor-pointer hover:opacity-80 text-dark-500 transition"
                         onClick={(e: any) => {

+ 22 - 20
src/modules/editor/components/Viewport/Slider/SliderRight/CompTree.tsx

@@ -165,25 +165,27 @@ export const CompTree = defineComponent({
     };
 
     return () => (
-      <Tree
-        class={treeStyle}
-        treeData={state.treeData}
-        v-model={[state.expandedKeys, "expandedKeys"]}
-        selectedKeys={[store.currCompId]}
-        blockNode={true}
-        draggable={true}
-        onDrop={onDrop}
-        onSelect={(ids) => {
+      <div class="!overflow-x-auto">
+        <Tree
+          class={treeStyle}
+          treeData={state.treeData}
+          v-model={[state.expandedKeys, "expandedKeys"]}
+          selectedKeys={[store.currCompId]}
+          blockNode={true}
+          draggable={true}
+          onDrop={onDrop}
+          onSelect={(ids) => {
           const id = (ids[0] as string) || state.expandedKeys.at(-2) || "root";
-          actions.pickComp(id);
-        }}
-      >
-        {{
-          title: (data: any) => {
-            return <CompNode title={data.title} id={data.key} />;
-          },
-        }}
-      </Tree>
+            actions.pickComp(id);
+          }}
+        >
+          {{
+            title: (data: any) => {
+              return <CompNode title={data.title} id={data.key} />;
+            },
+          }}
+        </Tree>
+      </div>
     );
   },
 });
@@ -209,8 +211,8 @@ const CompNode = defineComponent({
       return (
         <div class={nodeStyle}>
           <Image src={thumbnail} size={240} />
-          <span class="w-0 flex-1 truncate">{props.title}</span>
-          <span class="space-x-4px">
+          <span class="w-1/1 flex-1 whitespace-nowrap mr-30px">{props.title}</span>
+          <span class="space-x-4px whitespace-nowrap">
             {actions.map((action, i) =>
               action.getVisible.call(editor, comp) ? (
                 <action.component

+ 1 - 0
src/modules/editor/controllers/ScreenshotCtrl/index.ts

@@ -23,6 +23,7 @@ export class ScreenshotCtrl {
 
     
     if (options.ratio) {
+
       const result = await domtoimage.toJpeg(dom);
       const img = await new Promise<HTMLImageElement>((resolve) => {
         const image = new Image();

+ 1 - 0
src/modules/editor/controllers/SelectCtrl/ObjsContainer.ts

@@ -309,6 +309,7 @@ export class ObjsContainer {
     }
 
     updateSize() {
+        this.selected.forEach(s=>s.updateSize());
         this.init();
     }
 }

+ 14 - 0
src/modules/editor/controllers/SelectCtrl/compObj.ts

@@ -149,4 +149,18 @@ export class CompObject extends DisplayObject {
         this.worldTransform.apply(p,p);
         return p;
     }
+    updateSize() {
+        const c = this.comp;
+        if (c.layout.size ) {
+            if (c.layout.size[0]) {
+                this._width =  designSizeToPx(c.layout.size[0]);
+            }
+            if (c.layout.size[1]) {
+                this._height =  designSizeToPx(c.layout.size[1]);
+            }
+        }
+        // this.transform.setFromMatrix(Matrix.createFromMatrixStr(c.layout.transformMatrix || "matrix(1,0,0,1,0,0)"));
+        this.updateTransform();
+        this._boundsID++;
+    }
 }

+ 5 - 0
src/modules/editor/controllers/SelectCtrl/index.ts

@@ -659,6 +659,11 @@ export class SelectCtrl extends ModuleControl<EditorModule> {
         if (comp.layout.locked) {
           this.transferStyle.showGizmo = false;
         }
+        if (comp.compKey == "Text") {
+          if (!this.helper.isStreamCardChild(comp.id)) {
+            this.transferStyle.showGizmo = false;
+          } 
+        }
     }
   }
 

+ 41 - 1
src/modules/editor/module/actions/edit.tsx

@@ -315,6 +315,40 @@ export const editActions = EditorModule.action({
     //  console.log("contrc ", this.store.selected);
      ctrlcselected = this.store.selected.slice(0);
   },
+  copyLastSelected() {
+    if (this.store.currCompId && this.store.currCompId != "root") {
+      ctrlcselected = [this.store.currCompId]
+    }
+  },
+
+  setSameSize(isWidth:boolean) {
+   
+    const selectCtrl = this.controls.selectCtrl;
+    const objc = selectCtrl.objContainer as ObjsContainer;
+    if (this.store.selected.length == 1 ) {
+      this.store.currComp.layout.size[0] = 750;
+      objc.updateSize();
+  
+      selectCtrl.upgateGizmoStyle();
+      return;
+    }
+
+    const anchorBox = this.helper.findComp(this.store.lastSelected);
+    if (!anchorBox) return;
+
+ 
+   
+    objc.parent.children.forEach((c)=>{
+      const child = c as CompObject;
+      const r = child.getBox();
+      if (isWidth)  child.comp.layout.size[0] = anchorBox.layout.size[0];
+      else child.comp.layout.size[1] = anchorBox.layout.size[1];
+    })
+
+    objc.updateSize();
+    
+    selectCtrl.upgateGizmoStyle();
+  },
 
   toogleGroup() {
      if (this.store.selected.length > 1) {
@@ -394,7 +428,13 @@ export const editActions = EditorModule.action({
   removeComp(compId: string) {
 
     const paths = this.helper.getCompTrees(compId);
-    if (!paths[2]) return;
+    if (!paths[2]) {
+      if (this.helper.isStreamCard(compId)) {
+        this.actions.removeStreamCard(compId);
+        return;
+      }
+      return;
+    }
     compId = paths[2].id;
 
     if (this.helper.isCompCanDelete(compId)) {

+ 2 - 1
src/modules/editor/module/helpers/index.ts

@@ -108,8 +108,9 @@ export const helpers = EditorModule.helper({
     return i >= 0;
   },
   isCompCanDelete(compId: string): boolean {
-    return this.helper.isStreamCardChild(compId);
+    return this.helper.isStreamCardChild(compId) || (this.helper.isStreamCard(compId) && this.store.streamCardIds.length > 1);
   },
+
   isShowSaveComp(comp: DesignComp): boolean {
     if ( !this.helper.isStreamCardChild(comp.id) ) return false;
     return true;

+ 22 - 0
src/modules/editor/objects/Toolbars/layout.ts

@@ -65,4 +65,26 @@ export const LayoutToolbars = createToolbars({
             this.actions.setAlignY(2);
         },
     },
+
+    Copy: {
+        component: TipIcons.Copy,
+        getVisible(comp) { return !!this.store.lastSelected },
+        onClick(comp) {
+            this.actions.copyLastSelected();
+        },
+    },
+    SameWidth: {
+        component: TipIcons.SameWidth,
+        getVisible(comp) { return this.store.selected.length > 0 },
+        onClick(comp) {
+            this.actions.setSameSize(true);
+        },
+    },
+    SameHeight: {
+        component: TipIcons.SameHeight,
+        getVisible(comp) { return this.store.selected.length > 1 && !!this.store.lastSelected },
+        onClick(comp) {
+            this.actions.setSameSize(false);
+        },
+    },
 });

+ 4 - 0
src/modules/editor/objects/Toolbars/topToolbars.ts

@@ -7,6 +7,7 @@ export const TopToolbarsLeft: ToolbarItem[] = [
 
     
     toolbars.delete,
+    // LayoutToolbars.Copy,
     toolbars.layerUp,
     toolbars.layerDown,
     toolbars.align,
@@ -25,6 +26,9 @@ export const TopToolbarsLeft: ToolbarItem[] = [
     LayoutToolbars.YBottom,
     LayoutToolbars.yBetween,
     
+    LayoutToolbars.SameWidth,
+    LayoutToolbars.SameHeight,
+    
     Toolbars.text,
     toolbar,
 ]