Parcourir la source

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

liwei il y a 1 an
Parent
commit
f87ba020ef
29 fichiers modifiés avec 447 ajouts et 347 suppressions
  1. 2 6
      src/components/AssetsList.tsx
  2. 3 3
      src/modules/editor/components/CompUI/basicUI/Container/index.ts
  3. 11 7
      src/modules/editor/components/CompUI/basicUI/Image2/component.tsx
  4. 3 0
      src/modules/editor/components/CompUI/basicUI/Image2/index.ts
  5. 17 5
      src/modules/editor/components/CompUI/basicUI/Video/component.tsx
  6. 3 0
      src/modules/editor/components/CompUI/basicUI/Video/index.ts
  7. 13 10
      src/modules/editor/components/CompUI/basicUI/Web3D/component.tsx
  8. 3 0
      src/modules/editor/components/CompUI/basicUI/Web3D/index.ts
  9. 3 0
      src/modules/editor/components/CompUI/customUI/Cards/CardList/index.tsx
  10. 1 2
      src/modules/editor/components/CompUI/defines/createCompHooks.ts
  11. 7 0
      src/modules/editor/components/Viewport/Slider/SliderLeft/MySources.tsx
  12. 1 1
      src/modules/editor/components/Viewport/Slider/SliderLeft/index.tsx
  13. 1 1
      src/modules/editor/components/Viewport/Slider/SliderRight/CompTree.tsx
  14. 2 2
      src/modules/editor/components/Viewport/Toolbar/index.tsx
  15. 1 1
      src/modules/editor/controllers/CompUICtrl/index.ts
  16. 31 32
      src/modules/editor/controllers/DragAddCtrl/index.ts
  17. 58 0
      src/modules/editor/controllers/ScreenshotCtrl/index.ts
  18. 123 0
      src/modules/editor/controllers/TransferCtrl/GroupCtrl.ts
  19. 31 124
      src/modules/editor/module/actions/edit.ts
  20. 6 57
      src/modules/editor/module/helpers/index.ts
  21. 16 0
      src/modules/editor/objects/DesignTemp/DesignComp.ts
  22. 14 22
      src/modules/resource/actions/material.ts
  23. 40 31
      src/modules/resource/helper.ts
  24. 6 1
      src/pages/editor/EditPage/index.tsx
  25. 37 32
      src/pages/website/Material2/components/Material.tsx
  26. 6 2
      src/pages/website/Material2/controller.tsx
  27. 4 4
      src/pages/website/MyComps/components/CompItem.tsx
  28. 3 3
      src/pages/website/Promotion2/components/PromotionItem.tsx
  29. 1 1
      src/pages/website/Promotion2/components/ShareModal.tsx

+ 2 - 6
src/components/AssetsList.tsx

@@ -1,4 +1,3 @@
-import { css } from "@linaria/core";
 import { List } from "@queenjs/ui";
 import { Empty, Pagination, Spin } from "ant-design-vue";
 import { defineUI } from "queenjs";
@@ -17,7 +16,7 @@ export default defineUI({
       const loading = control.state.loading;
 
       return (
-        <div class={styles}>
+        <div>
           {loading && (
             <div class="h-200px flex items-center justify-center">
               <Spin spinning tip="加载中"></Spin>
@@ -35,6 +34,7 @@ export default defineUI({
                 <Pagination
                   size="default"
                   hideOnSinglePage
+                  showSizeChanger={false}
                   pageSize={control.state.size}
                   total={control.state.total}
                   current={control.state.page}
@@ -48,7 +48,3 @@ export default defineUI({
     };
   },
 });
-
-const styles = css`
-  /*  */
-`;

+ 3 - 3
src/modules/editor/components/CompUI/basicUI/Container/index.ts

@@ -15,9 +15,9 @@ export const { createComp, useCompData } = createCompHooks({
   },
   layout: {
     size: [750, 700],
-    background: {
-      color: "#ffffff",
-    },
+    // background: {
+    //   color: "#ffffff",
+    // },
   },
 });
 

+ 11 - 7
src/modules/editor/components/CompUI/basicUI/Image2/component.tsx

@@ -14,13 +14,17 @@ export const Component = defineComponent({
     const { store, controls, helper } = useEditor();
 
     async function changeVal() {
-      const url = await controls.pickCtrl.pickOneImage();
-      if (!url) return;
+      try {
+        const url = await controls.pickCtrl.pickOneImage();
+        if (!url) return;
 
-      comp.value.url = url;
-      comp.value.x = 0;
-      comp.value.y = 0;
-      comp.value.s = 1;
+        comp.value.url = url;
+        comp.value.x = 0;
+        comp.value.y = 0;
+        comp.value.s = 1;
+      } catch (error) {
+        console.log(error);
+      }
     }
 
     return () => {
@@ -51,7 +55,7 @@ export const Component = defineComponent({
                 ? value.url
                 : value.url + "?editMode=" + store.isEditMode
             }
-            onLoad={(e) => {
+            onLoad={() => {
               if (helper.isCurrComp(props.compId)) {
                 controls.transferCtrl.initStyle();
               }

+ 3 - 0
src/modules/editor/components/CompUI/basicUI/Image2/index.ts

@@ -11,6 +11,9 @@ export const options = {
 
 export const { createComp, useCompData } = createCompHooks({
   value: { url: Dict_Imgs.Default, x: 0, y: 0, s: 1 },
+  layout: {
+    size: [400, 400],
+  },
 });
 
 export const Form = createAttrsForm([

+ 17 - 5
src/modules/editor/components/CompUI/basicUI/Video/component.tsx

@@ -1,4 +1,4 @@
-import { defineComponent } from "vue";
+import { defineComponent, watch } from "vue";
 import { string } from "vue-types";
 import { useCompData } from ".";
 import { View } from "../View";
@@ -12,14 +12,26 @@ export const Component = defineComponent({
   },
   setup(props) {
     const { store, controls } = useEditor();
-    const { value } = useCompData(props.compId);
+    const comp = useCompData(props.compId);
+    const { value } = comp;
 
     async function changeVal() {
-      const url = await controls.pickCtrl.pickOneImage();
-      if (!url) return;
-      value.url = url;
+      try {
+        const url = await controls.pickCtrl.pickOneImage();
+        if (!url) return;
+        value.url = url;
+      } catch (error) {
+        console.log(error);
+      }
     }
 
+    watch(
+      () => [value.ratio],
+      () => {
+        comp.setH(comp.getW() / value.ratio);
+      }
+    );
+
     return () => {
       const options: any = {};
       if (value.autoplay) options.autoplay = true;

+ 3 - 0
src/modules/editor/components/CompUI/basicUI/Video/index.ts

@@ -16,6 +16,9 @@ export const { createComp, useCompData } = createCompHooks({
     loop: true,
     controls: true,
   },
+  layout: {
+    size: [750, 750],
+  },
 });
 
 export const Form = createAttrsForm([

+ 13 - 10
src/modules/editor/components/CompUI/basicUI/Web3D/component.tsx

@@ -1,8 +1,8 @@
 import { Icon3D } from "@/assets/icons";
 import { useEditor } from "@/modules/editor";
 import { css } from "@linaria/core";
-import { queenApi, useModal } from "queenjs";
-import { defineComponent, reactive } from "vue";
+import { Effect, queenApi, useModal } from "queenjs";
+import { defineComponent, reactive, watch, watchEffect } from "vue";
 import { string } from "vue-types";
 import { useCompData } from ".";
 import { View } from "../View";
@@ -15,7 +15,8 @@ export const Component = defineComponent({
   },
   setup(props) {
     const { store } = useEditor();
-    const { value } = useCompData(props.compId);
+    const comp = useCompData(props.compId);
+    const { value } = comp;
 
     async function pickPack() {
       // await controls.pickCtrl.onPickPack();
@@ -38,6 +39,13 @@ export const Component = defineComponent({
       show3d: false,
     });
 
+    watch(
+      () => [value.ratio],
+      () => {
+        comp.setH(comp.getW() / value.ratio);
+      }
+    );
+
     return () => {
       return (
         <View
@@ -45,16 +53,11 @@ export const Component = defineComponent({
           onDblclick={store.isEditMode ? pickPack : undefined}
         >
           {state.show3d ? (
-            <iframe
-              class="w-full border-none"
-              src={value.url}
-              style={{ aspectRatio: value.ratio }}
-            />
+            <iframe class="w-full border-none" src={value.url} />
           ) : (
             <>
               <Image
-                class="w-full pointer-events-none"
-                style={{ aspectRatio: value.ratio }}
+                class="w-full h-full pointer-events-none object-cover"
                 size={480}
                 src={value.poster}
               />

+ 3 - 0
src/modules/editor/components/CompUI/basicUI/Web3D/index.ts

@@ -17,6 +17,9 @@ export const { createComp, useCompData } = createCompHooks({
     poster: Dict_Imgs.Default,
     ratio: 1,
   },
+  layout: {
+    size: [750, 750]
+  }
 });
 
 export const Form = createAttrsForm([

+ 3 - 0
src/modules/editor/components/CompUI/customUI/Cards/CardList/index.tsx

@@ -39,6 +39,9 @@ export const { createComp, useCompData, useCreateChild } = createCompHooks({
               url: thumb,
               ...offset,
             },
+            layout: {
+              size: [0, 0]
+            }
           }),
           desc: createCompId("Text", {
             value: `<p style="text-align:center;">这是一个小标题</p>`,

+ 1 - 2
src/modules/editor/components/CompUI/defines/createCompHooks.ts

@@ -30,10 +30,9 @@ export function createCompHooks<T, C extends { [name: string]: AnyFun }>(
   function useCompData(compId: string) {
     const editor = useEditor();
     const comp = editor.store.designData.compMap[compId];
-    return comp as {
+    return comp as DesignComp & {
       value: T;
       children: { [name in keyof C]: ReturnType<C[name]> };
-      layout: Layout;
     };
   }
 

+ 7 - 0
src/modules/editor/components/Viewport/Slider/SliderLeft/MySources.tsx

@@ -0,0 +1,7 @@
+import { defineComponent } from "vue";
+
+export const MySources = defineComponent({
+  setup() {
+    return () => <div>我的素材</div>;
+  },
+});

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

@@ -57,7 +57,7 @@ export default defineUI({
                   <div
                     class="draggable-item p-4px text-center"
                     onClick={() =>
-                      editor.actions.addCompToDesign(item.compKey as ICompKeys)
+                      editor.actions.clickCompToDesign(item.compKey as ICompKeys)
                     }
                   >
                     <img

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

@@ -91,7 +91,7 @@ const CompNode = defineComponent({
       return (
         <div class={nodeStyle}>
           <Image src={thumbnail} size={240} />
-          <span class="flex-1">{props.title}</span>
+          <span class="w-0 flex-1 truncate">{props.title}</span>
           <span class="space-x-4px">
             {actions.map((action) =>
               action.getVisible.call(editor, comp) ? (

+ 2 - 2
src/modules/editor/components/Viewport/Toolbar/index.tsx

@@ -9,7 +9,7 @@ export default defineUI({
     const { history } = controls.historyCtrl;
     return () => (
       <>
-        <div class="absolute top-20px left-20px space-x-10px">
+        <div class="absolute top-20px left-20px space-x-10px z-10">
           <TipIcons.Undo
             disable={!history.state.canUndo}
             class={btnCls}
@@ -21,7 +21,7 @@ export default defineUI({
             onClick={() => history.redo()}
           />
         </div>
-        <div class="absolute top-20px right-20px">
+        <div class="absolute top-20px right-20px z-10">
           <TipIcons.Screenshot
             class={btnCls}
             onClick={() => actions.updateThumbnailByScreenshot(true)}

+ 1 - 1
src/modules/editor/controllers/CompUICtrl/index.ts

@@ -48,7 +48,7 @@ export class CompUICtrl extends ModuleControl<EditorModule> {
       });
     });
   }
-  private async initUserUI() {
+  async initUserUI() {
     const listCtrl = new PageListController<
       { _id: string; title: string; thumbnail: string },
       any

+ 31 - 32
src/modules/editor/controllers/DragAddCtrl/index.ts

@@ -2,45 +2,44 @@ import { ModuleControl } from "queenjs";
 import { EditorModule } from "../../module";
 
 export class DragAddCtrl extends ModuleControl<EditorModule> {
-    dragingCompKey = ""
+  dragingCompKey = "";
 
-    _cancel?:()=>void
-    _mouseUping = false
+  _cancel?: () => void;
+  _mouseUping = false;
 
-    updateCompKey(k:string) {
-        if (this._mouseUping) return;
+  updateCompKey(k: string) {
+    if (this._mouseUping) return;
 
-        const isSame = (k == this.dragingCompKey);
-        this.dragingCompKey = k;
-        if (!isSame && k) {
-            if (this._cancel) this._cancel();
-            this._cancel = this.initEvent();
-        }
+    const isSame = k == this.dragingCompKey;
+    this.dragingCompKey = k;
+    if (!isSame && k) {
+      if (this._cancel) this._cancel();
+      this._cancel = this.initEvent();
     }
+  }
 
-    initEvent() {
-        const scope = this;
+  initEvent() {
+    const scope = this;
 
-        function mouseup(e:MouseEvent) {
-            console.log("mouseup=>", scope.dragingCompKey)
-            scope._mouseUping = true;
-            setTimeout(() => {
-                scope._mouseUping = false;
-            }, 400);
+    function mouseup(e: MouseEvent) {
+      console.log("mouseup=>", scope.dragingCompKey);
+      scope._mouseUping = true;
+      setTimeout(() => {
+        scope._mouseUping = false;
+      }, 1000);
 
-            if (scope._cancel) scope._cancel();
+      if (scope._cancel) scope._cancel();
 
-            if (!scope.dragingCompKey ) return;
-            scope.actions.addCompToDesign(scope.dragingCompKey as any)
-            scope.dragingCompKey = "";
-          
-        }
+      if (!scope.dragingCompKey) return;
+      scope.actions.dragCompToDesign(e, scope.dragingCompKey as any);
+      scope.dragingCompKey = "";
+    }
 
-        document.addEventListener("mouseup", mouseup)
+    document.addEventListener("mouseup", mouseup);
 
-        return ()=> {
-            document.removeEventListener("mouseup", mouseup)
-            scope._cancel = undefined;
-        }
-    }
-}
+    return () => {
+      document.removeEventListener("mouseup", mouseup);
+      scope._cancel = undefined;
+    };
+  }
+}

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

@@ -0,0 +1,58 @@
+import domtoimage from "dom-to-image";
+
+export class ScreenshotCtrl {
+  async snap(options: { element: HTMLElement; ratio?: number }): Promise<Blob> {
+    const dom = options.element;
+
+    const transferEl = document.querySelector(".transfer") as
+      | HTMLElement
+      | undefined;
+    if (transferEl) {
+      transferEl.style.display = "none";
+    }
+
+    if (options.ratio) {
+      const result = await domtoimage.toJpeg(dom);
+      const img = await new Promise<HTMLImageElement>((resolve) => {
+        const image = new Image();
+        image.src = result;
+        image.onload = function () {
+          if (transferEl) {
+            transferEl.style.display = "block";
+          }
+          resolve(image);
+        };
+      });
+      const canvas = document.createElement("canvas");
+      canvas.width = img.naturalWidth;
+      canvas.height = Math.min(
+        img.naturalWidth / options.ratio,
+        img.naturalHeight
+      );
+      const ctx = canvas.getContext("2d");
+      ctx?.drawImage(
+        img,
+        0,
+        0,
+        canvas.width,
+        canvas.height,
+        0,
+        0,
+        canvas.width,
+        canvas.height
+      );
+      return new Promise((resolve) => {
+        canvas.toBlob((blob) => {
+          if (transferEl) {
+            transferEl.style.display = "block";
+          }
+          if (blob) {
+            resolve(blob);
+          }
+        });
+      });
+    } else {
+      return domtoimage.toBlob(dom);
+    }
+  }
+}

+ 123 - 0
src/modules/editor/controllers/TransferCtrl/GroupCtrl.ts

@@ -1,5 +1,7 @@
 import { ModuleControl } from "queenjs";
 import { EditorModule } from "../../module";
+import { DesignComp } from "../../objects/DesignTemp/DesignComp";
+import { Matrix } from "./Matrix";
 
 export class GroupActionCtrl extends ModuleControl<EditorModule> {
   init() {
@@ -20,4 +22,125 @@ export class GroupActionCtrl extends ModuleControl<EditorModule> {
   destroy() {
     document.body.removeEventListener("keydown", this.enableGroupMode);
   }
+
+  async combineGroup() {
+    const { helper, store } = this;
+    const { groupIds } = store;
+    if (groupIds.length < 2) return;
+    const compsRect: Record<
+      string,
+      { t: number; l: number; r: number; b: number }
+    > = {};
+    const parentComp = helper.findParentComp(groupIds[0]) as DesignComp;
+    const parentRect = parentComp.$el.getBoundingClientRect();
+    groupIds.forEach((id) => {
+      const comp = helper.findComp(id) as DesignComp;
+      const itemRect = comp.$el.getBoundingClientRect();
+      compsRect[id] = {
+        t: itemRect.top - parentRect.top,
+        l: itemRect.left - parentRect.left,
+        r: itemRect.right - parentRect.left,
+        b: itemRect.bottom - parentRect.top,
+      };
+    });
+
+    const confVals = Object.values(compsRect);
+    const groupConf = {
+      t: Math.min(...confVals.map((d) => d.t)),
+      l: Math.min(...confVals.map((d) => d.l)),
+      r: Math.max(...confVals.map((d) => d.r)),
+      b: Math.max(...confVals.map((d) => d.b)),
+    };
+
+    const groupId = await this.store.insertCompContainer("Group", parentComp);
+
+    const groupComp = helper.findComp(groupId) as DesignComp;
+
+    groupComp.layout = {
+      size: [
+        helper.pxToDesignSize(groupConf.r - groupConf.l),
+        helper.pxToDesignSize(groupConf.b - groupConf.t),
+      ],
+      position: "absolute",
+      transform: {
+        x: helper.pxToDesignSize(groupConf.l),
+        y: helper.pxToDesignSize(groupConf.t),
+      },
+    };
+
+    groupIds.forEach((id) => {
+      const comp = helper.findComp(id) as DesignComp;
+      comp.layout.transform || (comp.layout.transform = {});
+      comp.layout.transform.x =
+        (comp.layout.transform.x || 0) - (groupComp.layout.transform?.x || 0);
+
+      comp.layout.transform.y =
+        (comp.layout.transform.y || 0) - (groupComp.layout.transform?.y || 0);
+    });
+
+    groupComp.children.default = parentComp.children.default?.filter((d) =>
+      groupIds.includes(d)
+    );
+    parentComp.children.default = parentComp.children.default?.filter(
+      (d) => !groupIds.includes(d)
+    );
+
+    return groupId;
+  }
+
+  async cancelGroup(groupComp: DesignComp) {
+    const { helper } = this;
+    const groupChildIds = groupComp.children.default as string[];
+
+    const parentComp = helper.findParentComp(groupComp.id) as DesignComp;
+
+    const parentMatrix = new Matrix();
+
+    groupChildIds.forEach((id) => {
+      const comp = helper.findComp(id) as DesignComp;
+
+      parentMatrix.setFormDiv(groupComp.$el);
+      const originArr = window
+        .getComputedStyle(groupComp.$el)
+        .transformOrigin.split(" ")
+        .map(parseFloat);
+
+      const porigin = new Matrix();
+      porigin.translate(originArr[0], originArr[1]);
+      const invOrigin = new Matrix();
+      invOrigin.translate(-originArr[0], -originArr[1]);
+
+      const childOrigArr = window
+        .getComputedStyle(comp.$el)
+        .transformOrigin.split(" ")
+        .map(parseFloat);
+      const corigin = new Matrix();
+      corigin.translate(childOrigArr[0], childOrigArr[1]);
+      const cinvOrigin = new Matrix();
+      cinvOrigin.translate(-childOrigArr[0], -childOrigArr[1]);
+
+      const childMatrix = new Matrix();
+      childMatrix.setFormDiv(comp.$el);
+
+      const result = cinvOrigin
+        .multipy(porigin)
+        .multipy(parentMatrix)
+        .multipy(invOrigin)
+        .multipy(corigin)
+        .multipy(childMatrix);
+
+      comp.layout.transform || (comp.layout.transform = {});
+      comp.layout.transform.x = helper.pxToDesignSize(result.getX());
+      comp.layout.transform.y = helper.pxToDesignSize(result.getY());
+      comp.layout.transform.s = result.getScale();
+      comp.layout.transform.r = result.getRotate();
+    });
+
+    const childIds = [...(parentComp.children.default as string[])];
+
+    const groupIndex = childIds.findIndex((id) => groupComp.id === id);
+    childIds.splice(groupIndex, 1, ...groupChildIds);
+
+    parentComp.children.default = childIds;
+  }
 }

+ 31 - 124
src/modules/editor/module/actions/edit.ts

@@ -1,11 +1,34 @@
 import { cloneDeep, pick, set } from "lodash";
 import { Exception, queenApi } from "queenjs";
 import { EditorModule } from "..";
+import { ScreenshotCtrl } from "../../controllers/ScreenshotCtrl";
 import { DesignComp } from "../../objects/DesignTemp/DesignComp";
-import { Matrix } from "../../controllers/TransferCtrl/Matrix";
 import { ICompKeys, Layout } from "../../typings";
 
 export const editActions = EditorModule.action({
+  // 通过拖拽添加组件到画布
+  async dragCompToDesign(event: MouseEvent, compKey: ICompKeys) {
+    await this.actions.addCompToDesign(compKey);
+    const cardPoints = this.helper.getPointOffsetWith(
+      event,
+      this.store.currStreamCard.$el
+    );
+    const { currComp } = this.store;
+    currComp.translate(
+      375 - (currComp.layout.size?.[0] || 750) / 2,
+      this.helper.pxToDesignSize(cardPoints.y)
+    );
+  },
+  // 通过点击添加组件到画布
+  async clickCompToDesign(compKey: ICompKeys) {
+    await this.actions.addCompToDesign(compKey);
+    const { currStreamCard, currComp } = this.store;
+
+    const y = currStreamCard.getH();
+    currStreamCard.setH(y + currComp.getH());
+    currComp.translate(0, y);
+  },
+
   // 添加组件到画布
   async addCompToDesign(compKey: ICompKeys, index?: number) {
     if (!this.store.currStreamCardId) {
@@ -68,7 +91,7 @@ export const editActions = EditorModule.action({
     if (this.store.currCompId == compId) {
       return;
     }
- 
+
     this.store.setCurrComp(compId);
     if (this.store.currCompId == this.store.currStreamCardId) {
       this.controls.transferCtrl.destroy();
@@ -116,7 +139,7 @@ export const editActions = EditorModule.action({
   async saveAsComp(comp: DesignComp) {
     try {
       // 组件封面
-      const blob = await this.helper.screenshot({
+      const blob = await new ScreenshotCtrl().snap({
         element: comp.$el,
       });
       const thumbnail = URL.createObjectURL(blob);
@@ -141,6 +164,7 @@ export const editActions = EditorModule.action({
       await this.controls.uploader.uploadBlobs(data);
       await this.https.createComp(data);
       queenApi.messageSuccess("保存成功");
+      this.controls.compUICtrl.initUserUI();
     } catch (error: any) {
       throw Exception.error(error.toString());
     } finally {
@@ -176,7 +200,7 @@ export const editActions = EditorModule.action({
       const rootComp = this.helper.findRootComp();
       if (!rootComp) return;
       queenApi.showLoading("截屏中");
-      const blob = await this.helper.screenshot({
+      const blob = await new ScreenshotCtrl().snap({
         element: rootComp.$el,
         ratio: this.store.isEditComp ? 0 : 1,
       });
@@ -256,133 +280,16 @@ export const editActions = EditorModule.action({
   },
   // 关闭组合模式
   async disableGroupMode() {
-    const groupId = await this.actions.combineGroupComps();
+    const groupId = await this.controls.transferCtrl.groupCtrl.combineGroup();
     if (groupId) {
       this.store.setCurrComp(groupId);
     }
     this.store.setGroupIds([]);
     this.store.setGroupMode(false);
   },
-  // 合并组件
-  async combineGroupComps() {
-    const { helper, store } = this;
-    const { groupIds } = store;
-    if (groupIds.length < 2) return;
-    const compsRect: Record<
-      string,
-      { t: number; l: number; r: number; b: number }
-    > = {};
-    const parentComp = helper.findParentComp(groupIds[0]) as DesignComp;
-    const parentRect = parentComp.$el.getBoundingClientRect();
-    groupIds.forEach((id) => {
-      const comp = helper.findComp(id) as DesignComp;
-      const itemRect = comp.$el.getBoundingClientRect();
-      compsRect[id] = {
-        t: itemRect.top - parentRect.top,
-        l: itemRect.left - parentRect.left,
-        r: itemRect.right - parentRect.left,
-        b: itemRect.bottom - parentRect.top,
-      };
-    });
-
-    const confVals = Object.values(compsRect);
-    const groupConf = {
-      t: Math.min(...confVals.map((d) => d.t)),
-      l: Math.min(...confVals.map((d) => d.l)),
-      r: Math.max(...confVals.map((d) => d.r)),
-      b: Math.max(...confVals.map((d) => d.b)),
-    };
-
-    const groupId = await this.store.insertCompContainer("Group", parentComp);
-
-    const groupComp = helper.findComp(groupId) as DesignComp;
-
-    groupComp.layout = {
-      size: [
-        helper.pxToDesignSize(groupConf.r - groupConf.l),
-        helper.pxToDesignSize(groupConf.b - groupConf.t),
-      ],
-      position: "absolute",
-      transform: {
-        x: helper.pxToDesignSize(groupConf.l),
-        y: helper.pxToDesignSize(groupConf.t),
-      },
-    };
-
-    groupIds.forEach((id) => {
-      const comp = helper.findComp(id) as DesignComp;
-      comp.layout.transform || (comp.layout.transform = {});
-      comp.layout.transform.x =
-        (comp.layout.transform.x || 0) - (groupComp.layout.transform?.x || 0);
-
-      comp.layout.transform.y =
-        (comp.layout.transform.y || 0) - (groupComp.layout.transform?.y || 0);
-    });
-
-    groupComp.children.default = parentComp.children.default?.filter((d) =>
-      groupIds.includes(d)
-    );
-    parentComp.children.default = parentComp.children.default?.filter(
-      (d) => !groupIds.includes(d)
-    );
-
-    return groupId;
-  },
   // 取消打组
   cancelGroupComps(groupComp: DesignComp) {
-    const { helper } = this;
-    const groupChildIds = groupComp.children.default as string[];
-
-    const parentComp = helper.findParentComp(groupComp.id) as DesignComp;
-
-    const parentMatrix = new Matrix();
-
-    groupChildIds.forEach((id) => {
-      const comp = helper.findComp(id) as DesignComp;
-
-      parentMatrix.setFormDiv(groupComp.$el);
-      const originArr = window
-        .getComputedStyle(groupComp.$el)
-        .transformOrigin.split(" ")
-        .map(parseFloat);
-
-      const porigin = new Matrix();
-      porigin.translate(originArr[0], originArr[1]);
-      const invOrigin = new Matrix();
-      invOrigin.translate(-originArr[0], -originArr[1]);
-
-      const childOrigArr = window
-        .getComputedStyle(comp.$el)
-        .transformOrigin.split(" ")
-        .map(parseFloat);
-      const corigin = new Matrix();
-      corigin.translate(childOrigArr[0], childOrigArr[1]);
-      const cinvOrigin = new Matrix();
-      cinvOrigin.translate(-childOrigArr[0], -childOrigArr[1]);
-
-      const childMatrix = new Matrix();
-      childMatrix.setFormDiv(comp.$el);
-
-      const result = cinvOrigin
-        .multipy(porigin)
-        .multipy(parentMatrix)
-        .multipy(invOrigin)
-        .multipy(corigin)
-        .multipy(childMatrix);
-
-      comp.layout.transform || (comp.layout.transform = {});
-      comp.layout.transform.x = helper.pxToDesignSize(result.getX());
-      comp.layout.transform.y = helper.pxToDesignSize(result.getY());
-      comp.layout.transform.s = result.getScale();
-      comp.layout.transform.r = result.getRotate();
-    });
-
-    const childIds = [...(parentComp.children.default as string[])];
-
-    const groupIndex = childIds.findIndex((id) => groupComp.id === id);
-    childIds.splice(groupIndex, 1, ...groupChildIds);
-
-    parentComp.children.default = childIds;
-    this.store.setCurrComp(groupChildIds[0]);
+    this.controls.transferCtrl.groupCtrl.cancelGroup(groupComp);
+    this.store.setCurrComp(groupComp.children.default?.[0] as string);
   },
 });

+ 6 - 57
src/modules/editor/module/helpers/index.ts

@@ -1,4 +1,3 @@
-import domtoimage from "dom-to-image";
 import { EditorModule } from "..";
 import { DesignComp } from "../../objects/DesignTemp/DesignComp";
 import { createCompStyle } from "../../objects/DesignTemp/creates/createCompStyle";
@@ -103,61 +102,11 @@ export const helpers = EditorModule.helper({
       }
     });
   },
-  async screenshot(options: {
-    element: HTMLElement;
-    ratio?: number;
-  }): Promise<Blob> {
-    const dom = options.element;
-
-    const transferEl = document.querySelector(".transfer") as
-      | HTMLElement
-      | undefined;
-    if (transferEl) {
-      transferEl.style.display = "none";
-    }
-
-    if (options.ratio) {
-      const result = await domtoimage.toJpeg(dom);
-      const img = await new Promise<HTMLImageElement>((resolve) => {
-        const image = new Image();
-        image.src = result;
-        image.onload = function () {
-          if (transferEl) {
-            transferEl.style.display = "block";
-          }
-          resolve(image);
-        };
-      });
-      const canvas = document.createElement("canvas");
-      canvas.width = img.naturalWidth;
-      canvas.height = Math.min(
-        img.naturalWidth / options.ratio,
-        img.naturalHeight
-      );
-      const ctx = canvas.getContext("2d");
-      ctx?.drawImage(
-        img,
-        0,
-        0,
-        canvas.width,
-        canvas.height,
-        0,
-        0,
-        canvas.width,
-        canvas.height
-      );
-      return new Promise((resolve) => {
-        canvas.toBlob((blob) => {
-          if (transferEl) {
-            transferEl.style.display = "block";
-          }
-          if (blob) {
-            resolve(blob);
-          }
-        });
-      });
-    } else {
-      return domtoimage.toBlob(dom);
-    }
+  getPointOffsetWith(e: MouseEvent, dom: HTMLElement) {
+    const domRect = dom.getBoundingClientRect();
+    return {
+      x: e.clientX - domRect.left,
+      y: e.clientY - domRect.top,
+    };
   },
 });

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

@@ -44,4 +44,20 @@ export class DesignComp {
     const w = this.layout.size?.[0];
     return !w || w === 750;
   }
+
+  translate(x: number, y: number) {
+    this.layout.transform || (this.layout.transform = {});
+    x && (this.layout.transform.x = x);
+    y && (this.layout.transform.y = y);
+  }
+  getW() {
+    return this.layout.size?.[0] || 0;
+  }
+  getH() {
+    return this.layout.size?.[1] || 0;
+  }
+  setH(height: number) {
+    if (!this.layout.size) this.layout.size = [];
+    this.layout.size[1] = height;
+  }
 }

+ 14 - 22
src/modules/resource/actions/material.ts

@@ -3,29 +3,21 @@ import { ResourceModule } from "..";
 
 export const materialActions = ResourceModule.action({
   async uploadMaterial() {
-    const [blob] = await queenApi.selectFile({ accept: "image/*, video/*" });
-
-    // const url = URL.createObjectURL(blob);
-    // const data = { url, size: blob.size };
-    // await this.controls.uploader.uploadBlobs(data, {
-    //   createPathKey: this.helpers.createFileName,
-    // });
+    const files = await this.helper.uploadResource({
+      accept: "image/*, video/mp4",
+      multiple: true,
+    });
 
-    const data = await this.controls.uploader.uploadFile(blob, "queenshow");
+    let souceObj = files[0];
+    for (const key in files) {
+      souceObj = files[key];
+      await this.https.createResource(souceObj);
+    }
 
-    const souceObj = {
-      file: data,
-      fileType: blob.type.split("/")[0],
-      from: "upload",
+    this.controls.materialListCtrl.state.query = {
+      fileType: this.store.type,
     };
-    await this.https.createResource(souceObj);
-    // this.store.setSourceType(souceObj.fileType);
-
-    // this.controls.materialListCtrl.state.query = {
-    //   fileType: this.store.type,
-    // };
-    // this.controls.materialListCtrl.loadPage(1);
-
+    this.controls.materialListCtrl.loadPage(1);
     return souceObj;
   },
 
@@ -36,7 +28,7 @@ export const materialActions = ResourceModule.action({
     });
     if (!res) return;
     await this.https.deleteResource(record._id);
-    this.controls.materialListCtrl.fresh();
+    // this.controls.materialListCtrl.fresh();
   },
 
   downloadMaterial(record) {
@@ -45,7 +37,7 @@ export const materialActions = ResourceModule.action({
 
   async selectMaterial(record) {
     const _params = new URLSearchParams(decodeURIComponent(location.search));
-    const host = _params.get("host")
+    const host = _params.get("host");
 
     if (location.host == "www.infish.cn") {
       const url = `${location.origin}/projects/queenshow/index.html?host=${host}#/create/${record._id}`;

+ 40 - 31
src/modules/resource/helper.ts

@@ -32,40 +32,49 @@ export const helper = ResourceModule.helper({
     return ctrl;
   },
 
-  createSourceController() {
-    const { controls, actions } = this;
+  // createSourceController() {
+  //   const { controls, actions } = this;
 
-    const ctrl = new MaterialController();
-    ctrl.imageCtrl = controls.materialImageListCtrl;
-    ctrl.vidoeCtrl = controls.materialVideoListCtrl;
-    ctrl.taskCtrl = controls.renderTaskListCtrl;
-    ctrl.tplCtrl = controls.matTempListCtrl;
+  //   const ctrl = new MaterialController();
+  //   ctrl.imageCtrl = controls.materialImageListCtrl;
+  //   ctrl.vidoeCtrl = controls.materialVideoListCtrl;
+  //   ctrl.taskCtrl = controls.renderTaskListCtrl;
+  //   ctrl.tplCtrl = controls.matTempListCtrl;
 
-    ctrl.onBtnClick = async function (name: string) {
-      if (name == "upload") {
-        const uploaded = await actions.uploadMaterial();
-        ctrl.switchTab(uploaded.fileType, false);
-        ctrl.getCurrControl().loadPage(1);
-        return;
-      }
-      ctrl.showDialog(name);
-    };
-    ctrl.onItemClick = function (name, record) {
-      if (name == "delete") return actions.deleteMaterial(record);
-      return actions.downloadMaterial(record);
-    };
-    return ctrl;
-  },
+  //   ctrl.onBtnClick = async function (name: string) {
+  //     if (name == "upload") {
+  //       const uploaded = await actions.uploadMaterial();
+  //       ctrl.switchTab(uploaded.fileType, false);
+  //       ctrl.getCurrControl().loadPage(1);
+  //       return;
+  //     }
+  //     ctrl.showDialog(name);
+  //   };
+  //   ctrl.onItemClick = function (name, record) {
+  //     if (name == "delete") return actions.deleteMaterial(record);
+  //     return actions.downloadMaterial(record);
+  //   };
+  //   return ctrl;
+  // },
 
-  async uploadResource(accept = "image/*") {
-    const [blob] = await queenApi.selectFile({ accept });
-    const data = await this.controls.uploader.uploadFile(blob, "queenshow");
+  async uploadResource(opts?: { accept?: string; multiple?: boolean }) {
+    const result = [];
+    const blobs = await queenApi.selectFile(opts);
 
-    const souceObj = {
-      file: data,
-      fileType: blob.type.split("/")[0],
-      from: "upload",
-    };
-    return souceObj;
+    queenApi.showLoading("上传中……");
+
+    for (const key in blobs) {
+      const blob = blobs[key];
+      const file = await this.controls.uploader.uploadFile(blob, "queenshow");
+      const souceObj = {
+        file,
+        fileType: blob.type.split("/")[0],
+        from: "upload",
+      };
+      result.push(souceObj);
+    }
+    
+    queenApi.hideLoading();
+    return result;
   },
 });

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

@@ -10,7 +10,12 @@ export default defineComponent(() => {
 
   const params = new URLSearchParams(location.hash.split("?")[1]);
   editor.actions.switchMode((params.get("mode") || "editPage") as EditorMode);
-  editor.actions.initDesign(params.get("id") || "");
+  const prodId = params.get("id");
+  if (prodId) {
+    editor.actions.initDesign(prodId);
+  } else {
+    editor.jumpIndexHtml();
+  }
 
   editor.controls.pickCtrl.onPickImage = async (maxCount: number) => {
     if (maxCount <= 1) {

+ 37 - 32
src/pages/website/Material2/components/Material.tsx

@@ -7,51 +7,56 @@ import { any } from "vue-types";
 import MaterialItem from "./MaterialItem";
 import Toolbar from "./MaterialToolbar";
 
-
 export default defineUI({
-    props: {
-        Controller: any<MaterialController>().isRequired,
-    },
-    slots: {
-        Toolbar,
-        AssetsList,
-        MaterialItem,
-    },
+  props: {
+    Controller: any<MaterialController>().isRequired,
+  },
+  slots: {
+    Toolbar,
+    AssetsList,
+    MaterialItem,
+  },
 
-    setup(props, { slots }) {
-        onMounted(() => {
-             props.Controller.getCurrControl().loadPage(1);
-        });
+  setup(props, { slots }) {
+    onMounted(() => {
+      props.Controller.getCurrControl().loadPage(1);
+    });
 
         return ()=>{
-            const state = props.Controller.state;
+      const state = props.Controller.state;
             const control = props.Controller.getCurrControl()
-            
-            return (<div class={rootStyles}>
-              {
-                !state.isSelect &&  <h3 class="text-22px">我的素材</h3>
-              }
 
-            <slots.Toolbar Controller={props.Controller} />
+      return (
+        <div class={rootStyles}>
+          {!state.isSelect && (
+            <div class="flex items-baseline">
+              <h3 class="text-22px m-0">我的素材</h3>
+              <span class="ml-5px text-gray-300 text-12px">
+                (图片支持jpg、png、gif、svg,不超过5M,视频支持mp4,不超过200M)
+              </span>
+            </div>
+          )}
+
+          <slots.Toolbar Controller={props.Controller} />
 
-            <slots.AssetsList
-              columns={6}
-              class="mt-30px"
-              control={control}
-              item={(record: any) => (
-                <slots.MaterialItem
-                  record={record}
+          <slots.AssetsList
+            columns={6}
+            class="mt-30px"
+            control={control}
+            item={(record: any) => (
+              <slots.MaterialItem
+                record={record}
                   use={ state.currTab == "task" ? "task" : (state.isSelect? "select": "show")}
-                  onDelete={() => props.Controller.onItemClick("delete", record)}
+                onDelete={() => props.Controller.onItemClick("delete", record)}
                   onDownload={() =>props.Controller.onItemClick("download", record)}
                   onUse={()=>props.Controller.onItemClick("use", record)}
                   onPreview={() =>props.Controller.onItemClick("preview", record)}
-                />
-              )}
-            />
+              />
+            )}
+          />
           </div>);
         }
-    },
+  },
 
 })
 

+ 6 - 2
src/pages/website/Material2/controller.tsx

@@ -55,8 +55,12 @@ export default function createController(resource:any, isSelectModel:boolean, se
       }
       showModal(name);
     };
-    ctrl.onItemClick = function (name, record) {
-      if (name == "delete") return actions.deleteMaterial(record);
+    ctrl.onItemClick = async function (name, record) {
+      if (name == "delete") {
+         await actions.deleteMaterial(record);
+         this.getCurrControl().fresh();
+         return;
+      }
       else if (name == "preview") return showPreviewModal({
         url: record.file.url,
         fileType: record.fileType,

+ 4 - 4
src/pages/website/MyComps/components/CompItem.tsx

@@ -16,7 +16,7 @@ export default defineUI({
       const { record } = props;
       return (
         <div class={cx(itemStyles, "relative")}>
-          <View ratio={1.4} class="overflow-hidden relative">
+          <View ratio={1.4} class=" relative">
             <Image
               class="h-1/1 w-1/1 !object-contain bg-[#ebebeb]"
               src={record?.thumbnail}
@@ -38,8 +38,8 @@ export default defineUI({
             </div> */}
           </View>
           <div class="item_footer rounded-b-4px flex items-center justify-between p-15px">
-            <div>
-              <div class="text-white text-bold">{record.title}</div>
+            <div class="w-0 flex-1">
+              <div class="text-white text-bold truncate">{record.title}</div>
               <div class="flex items-center text-opacity-60 text-white text-12px mt-5px">
                 {dayjs(record.updateTime).format("YYYY.MM.DD")}
               </div>
@@ -57,7 +57,7 @@ export default defineUI({
                 </Menu>
               }
             >
-              <IconMore class="text-22px cursor-pointer" />
+              <IconMore class="ml-10px text-22px cursor-pointer" />
             </Dropdown>
           </div>
         </div>

+ 3 - 3
src/pages/website/Promotion2/components/PromotionItem.tsx

@@ -74,8 +74,8 @@ export default defineUI({
             </div>
           </View>
           <div class="item_footer rounded-b-4px flex items-center justify-between p-15px">
-            <div>
-              <div class="text-white text-bold">{record.title}</div>
+            <div class="flex-1 w-0">
+              <div class="text-white text-bold truncate">{record.title}</div>
               <div class="flex items-center text-opacity-60 text-white text-12px mt-5px">
                 {dayjs(record.updateTime).format("YYYY.MM.DD")}
                 {/* 发布 */}
@@ -98,7 +98,7 @@ export default defineUI({
                 </Menu>
               }
             >
-              <IconMore class="text-22px cursor-pointer" />
+              <IconMore class="ml-10px text-22px cursor-pointer" />
             </Dropdown>
           </div>
         </div>

+ 1 - 1
src/pages/website/Promotion2/components/ShareModal.tsx

@@ -60,7 +60,7 @@ export default defineComponent({
                   class="absolute left-0 bottom-0 w-1/1 text-center py-5px text-14px bg-dark-200 bg-opacity-80 cursor-pointer"
                   onClick={async () => {
                     const res: any = await controller.changeThumbnail();
-                    state.thumbnail = res?.file?.url;
+                    state.thumbnail = res[0]?.file?.url;
                   }}
                 >
                   更换封面