Browse Source

Merge branch 'edev' into dev

qinyan 1 year ago
parent
commit
1fa92422d9

+ 25 - 22
src/modules/editor/components/CompUI/basicUI/Page/component.tsx

@@ -14,30 +14,33 @@ export const Component = defineComponent({
   setup(props, { slots }) {
     const editor = useEditor();
     const { helper } = editor;
-    const { children, layout, value } = useCompData(props.compId);
     const compRef = useCompRef(props.compId);
-    const compMusic = value.music || "";
-    const curValue = MusicOptions.find((e) => {
-      return e.value == compMusic;
-    });
-    return () => (
-      <div
-        ref={compRef}
-        style={helper.createStyle(layout || { size: [750] })}
-        class={["!h-auto", editor.store.isEditMode ? pageEditStyle : ""]}
-      >
-        <div class="relative">
-          {slots.Container?.(
-            children.default.map((compId) => {
-              const comp = helper.findComp(compId);
-              if (!comp) return;
-              return slots.CompItem?.(comp);
-            })
-          )}
-          {curValue?.value && !editor.store.isEditMode && <PageMusic />}
+
+    return () => {
+      const { children, layout, value } = useCompData(props.compId);
+      const compMusic = value.music || "";
+      const curValue = MusicOptions.find((e) => {
+        return e.value == compMusic;
+      });
+      return (
+        <div
+          ref={compRef}
+          style={helper.createStyle(layout || { size: [750] })}
+          class={["!h-auto", editor.store.isEditMode ? pageEditStyle : ""]}
+        >
+          <div class="relative">
+            {slots.Container?.(
+              children.default.map((compId) => {
+                const comp = helper.findComp(compId);
+                if (!comp) return;
+                return slots.CompItem?.(comp);
+              })
+            )}
+            {curValue?.value && !editor.store.isEditMode && <PageMusic />}
+          </div>
         </div>
-      </div>
-    );
+      );
+    };
   },
 });
 

+ 19 - 5
src/modules/editor/components/Viewport/Header/index.tsx

@@ -2,15 +2,25 @@ import { useEditor } from "@/modules/editor";
 import { Button, Dropdown } from "ant-design-vue";
 import { defineUI } from "queenjs";
 import { ShareBox } from "./ShareBox";
+import History from "../Toolbar/History";
 
 export default defineUI({
   setup() {
     const { store, actions, jumpIndexHtml } = useEditor();
+
     return () => (
-      <div class="flex justify-between">
-        <aside>
-          <img class="h-40px cursor-pointer" src={require("@/assets/imgs/Logo.png")} alt="logo" onClick={() => jumpIndexHtml()}/>
-        </aside>
+      <div class="relative flex justify-between">
+        <div class="flex items-center">
+          <aside>
+            <img
+              class="h-40px cursor-pointer"
+              src={require("@/assets/imgs/Logo.png")}
+              alt="logo"
+              onClick={() => jumpIndexHtml()}
+            />
+          </aside>
+          <History class="ml-100px" />
+        </div>
         {/* <Radio.Group
           value={store.mode}
           onChange={(e) => actions.switchMode(e.target.value)}
@@ -20,7 +30,11 @@ export default defineUI({
           </Radio.Button>
           <Radio.Button value="preview">预览</Radio.Button>
         </Radio.Group> */}
-
+        <div class="absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2">
+          <div class="text-16px font-bold text-light-50 max-w-240px truncate">
+            {store.designData?.title}
+          </div>
+        </div>
         <aside class="space-x-10px">
           {store.isEditPage && (
             <Dropdown

+ 63 - 0
src/modules/editor/components/Viewport/Slider/SliderLeft/Frames.tsx

@@ -0,0 +1,63 @@
+import { useEditor } from "@/modules/editor";
+import { Image, Loadmore } from "@queenjs/ui";
+import { defineUI } from "queenjs";
+import { Container, Draggable } from "vue-dndrop";
+import { any } from "vue-types";
+
+export default defineUI({
+  props: {
+    dataSource: any<
+      {
+        _id: string;
+        title: string;
+        thumbnail: string;
+      }[]
+    >().isRequired,
+  },
+  setup(props) {
+    const editor = useEditor();
+
+    return () => {
+      const { dataSource } = props;
+
+      return (
+        // <div class="flex flex-col overflow-hidden">
+        <Container
+          class="space-y-10px scrollbar"
+          behaviour="copy"
+          group-name="canvas"
+          animation-duration={0}
+          // get-child-payload={(index: number) => {
+          //   return props.components[index].compKey;
+          // }}
+        >
+          {dataSource.map((item) => {
+            return (
+              <Draggable>
+                <div
+                  class="text-center leading-50px bg-dark-50 rounded draggable-item"
+                  key={item._id}
+                  title={item.title}
+                  onClick={() => editor.actions.clickFrameToDesign(item)}
+                >
+                  <Image
+                    class="w-full rounded pointer-events-none"
+                    src={item.thumbnail}
+                    size={240}
+                  />
+                </div>
+              </Draggable>
+            );
+          })}
+        </Container>
+        //   <Loadmore
+        //     class="mt-20px"
+        //     loading={editor.controls.frameControl.listCtrl.state.loading}
+        //     canLoad={editor.controls.frameControl.listCtrl.state.canLoadNext}
+        //     onChange={editor.controls.frameControl.listCtrl.loadNextPage}
+        //   />
+        // </div>
+      );
+    };
+  },
+});

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

@@ -6,22 +6,26 @@ import { defineUI } from "queenjs";
 import { Container, Draggable } from "vue-dndrop";
 import CustomComps from "./CustomComps";
 import { MySources } from "./MySources";
+import Frames from "./Frames";
 
 export default defineUI({
   setup() {
     const editor = useEditor();
-    const { compUICtrl } = editor.controls;
+    const { compUICtrl, frameControl } = editor.controls;
 
     const tabs = [
-      { label: "模块组件", value: "senior" },
+      { label: "模板", value: "frame" },
+      { label: "组件", value: "senior" },
       { label: "我的组件", value: "user" },
       { label: "我的素材", value: "source" },
     ];
 
     const state = useReactive(() => ({
-      currTabType: "senior",
+      currTabType: "frame",
       basicComps() {
-        return ["Text", "Image", "Video", "Web3D"].map(key => compUICtrl.state.components.get(key) as any);
+        return ["Text", "Image", "Video", "Web3D"].map(
+          (key) => compUICtrl.state.components.get(key) as any
+        );
       },
       currComps() {
         return Array.from(compUICtrl.state.components.values()).filter(
@@ -82,13 +86,19 @@ export default defineUI({
               );
             })}
           </div>
-
-          {state.currTabType !== "source" ? (
+          {state.currTabType == "frame" && (
+            <Frames
+              class="flex-1 -mx-16px p-16px"
+              dataSource={frameControl.listCtrl.state.list}
+            />
+          )}
+          {(state.currTabType == "user" || state.currTabType == "senior") && (
             <CustomComps
               class="flex-1 -mx-16px p-16px"
               components={state.currComps}
             />
-          ) : (
+          )}
+          {state.currTabType == "source" && (
             <MySources class="flex-1 -mx-16px p-16px" />
           )}
         </div>

+ 42 - 0
src/modules/editor/components/Viewport/Toolbar/History.tsx

@@ -0,0 +1,42 @@
+import { useEditor } from "@/modules/editor";
+import { css } from "@linaria/core";
+import { defineUI } from "queenjs";
+import { TipIcons } from "../../TipIcons";
+
+export default defineUI({
+  setup() {
+    const { controls } = useEditor();
+
+    const { history } = controls.historyCtrl;
+
+    return () => {
+      return (
+        <div class="space-x-20px z-999">
+          <TipIcons.Undo
+            disable={
+              !controls.historyCtrl.state.enable || !history.state.canUndo
+            }
+            class={btnCls}
+            onClick={() => history.undo()}
+          />
+          <TipIcons.Redo
+            disable={
+              !controls.historyCtrl.state.enable || !history.state.canRedo
+            }
+            class={btnCls}
+            onClick={() => history.redo()}
+          />
+        </div>
+      );
+    };
+  },
+});
+
+const btnCls = css`
+  color: #fff;
+  font-size: 22px;
+  &.icon_disable {
+    color: #fff;
+    opacity: 0.5;
+  }
+`;

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

@@ -1,35 +1,26 @@
 import { useEditor } from "@/modules/editor";
+import { useLauncher } from "@/modules/launcher";
+import { css, cx } from "@linaria/core";
+import { Dropdown } from "ant-design-vue";
 import { defineUI } from "queenjs";
+import { reactive } from "vue";
 import { TipIcons } from "../../TipIcons";
-import { Dropdown } from "ant-design-vue";
-import { css } from "@linaria/core";
-import { useLauncher } from "@/modules/launcher";
 import AiText from "./AiText";
-import { reactive } from "vue";
+
 export default defineUI({
   setup() {
     const { actions, controls } = useEditor();
     const launcher = useLauncher();
-    const { history } = controls.historyCtrl;
+
     const state = reactive({
       aiVisible: false,
     });
+
     return () => (
-      <>
-        <div class="absolute top-20px left-20px space-x-10px z-999">
-          <TipIcons.Undo
-            disable={ !controls.historyCtrl.state.enable || !history.state.canUndo}
-            class={btnCls}
-            onClick={() => history.undo()}
-          />
-          <TipIcons.Redo
-            disable={ !controls.historyCtrl.state.enable || !history.state.canRedo}
-            class={btnCls}
-            onClick={() => history.redo()}
-          />
-        </div>
-        <div class="absolute top-20px right-20px space-x-10px z-999">
+      <div class="flex items-center justify-between px-15px py-12px">
+        <div class="space-x-10px z-999">
           <Dropdown
+            overlayClassName={dropdownStyles}
             overlay={
               <AiText
                 onVisible={(v) => {
@@ -38,16 +29,18 @@ export default defineUI({
               />
             }
             destroyPopupOnHide={true}
-            placement="bottom"
+            placement="bottomLeft"
             visible={state.aiVisible}
           >
             <TipIcons.AiText
-              class={btnCls}
+              class={cx(btnCls, state.aiVisible && "active")}
               onClick={() => {
                 state.aiVisible = !state.aiVisible;
               }}
             />
           </Dropdown>
+        </div>
+        <div class="space-x-10px z-999">
           <TipIcons.Screenshot
             class={btnCls}
             onClick={() => actions.updateThumbnailByScreenshot(true)}
@@ -55,7 +48,7 @@ export default defineUI({
         </div>
         <div class="absolute bottom-20px right-20px z-999">
           <TipIcons.QueenService
-            class={btnCls}
+            class={bottomBtnStyles}
             onClick={() => {
               launcher.showModal(<launcher.components.Viewport />, {
                 width: "400px",
@@ -63,14 +56,25 @@ export default defineUI({
             }}
           />
         </div>
-      </>
+      </div>
     );
   },
 });
 
 const btnCls = css`
+  padding: 5px;
+  &.active {
+    background: #1d1d1d;
+  }
+`;
+
+const bottomBtnStyles = css`
   padding: 10px;
   border-radius: 50%;
   background-color: #333;
   @apply shadow;
 `;
+
+const dropdownStyles = css`
+  /* transform: translateY(-20px); */
+`;

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

@@ -13,14 +13,14 @@ export default defineUI({
     Content,
     Toolbar,
   },
-  
+
   setup(props, { slots }) {
     return () => (
       <div class="flex flex-col h-1/1">
         <slots.Header class="p-16px bg-component border-bottom !border-2px" />
         <div class="flex flex-1 h-0">
           <slots.SliderLeft class="w-300px bg-component border-right !border-2px" />
-          <div class="flex-1 relative">
+          <div class="flex-1 relative flex flex-col">
             <slots.Toolbar />
             <slots.Content />
           </div>

+ 23 - 0
src/modules/editor/controllers/FrameCtrl/index.ts

@@ -0,0 +1,23 @@
+import { ModuleControl } from "queenjs";
+import { EditorModule } from "../../module";
+import { PageListController } from "@queenjs/controllers";
+import { reactive } from "vue";
+
+export class FrameControl extends ModuleControl<EditorModule> {
+  state = reactive({});
+
+  listCtrl = new PageListController<
+    { _id: string; title: string; thumbnail: string },
+    any
+  >(this.module.config.httpConfig);
+
+  init() {
+    this.initData();
+  }
+
+  private async initData() {
+    this.listCtrl.setCrudPrefix("/sys/h5");
+    this.listCtrl.state.size = 10000;
+    await this.listCtrl.loadPage(1);
+  }
+}

+ 26 - 3
src/modules/editor/module/actions/edit.ts

@@ -422,9 +422,7 @@ export const editActions = EditorModule.action({
     this.store.setCurrComp(groupComp.children.default?.[0] as string);
   },
 
- 
-
-  handleSelectMoving(key:string) {
+  handleSelectMoving(key: string) {
     if (this.store.selected.length < 1) return;
     let x = 0,
       y = 0;
@@ -445,4 +443,29 @@ export const editActions = EditorModule.action({
     this.controls.selectCtrl.translate(x * 0.5, y * 0.5);
     this.controls.selectCtrl.assistCtrl?.flashDrawCardDists();
   },
+
+  // clickFrameToDesign 点击模板到组件
+  async clickFrameToDesign(record) {
+    const res = await queenApi.showConfirm({
+      title: "",
+      content: "要替换正在编辑的内容?",
+    });
+    if (!res) return;
+    const frameData = await this.https.getFrameDetail(record._id);
+    const { compMap, content, desc, thumbnail, title } = frameData.result;
+
+    const designData = {
+      ...this.store.designData,
+      compMap,
+      content,
+      desc,
+      thumbnail,
+      title,
+    };
+
+    this.actions.selectObjs([]);
+    this.store.setCurrComp("root");
+    this.store.setDesignData(designData);
+    this.store.currStreamCardId = this.store.streamCardIds[0];
+  },
 });

+ 1 - 0
src/modules/editor/module/actions/init.ts

@@ -13,6 +13,7 @@ export const initActions = EditorModule.action({
     const { historyCtrl } = this.controls;
     historyCtrl.bindActions(Object.keys(editActions));
     this.controls.compUICtrl.init();
+    this.controls.frameControl.init();
     this.controls.mediaCtrl.init();
     createProxyEffect(this.store, (type, paths, value, oldValue) => {
       if (

+ 7 - 0
src/modules/editor/module/https/index.ts

@@ -27,4 +27,11 @@ export const https = EditorModule.http({
   createComp(data: any) {
     return this.request("/frame/create", { method: "POST", data });
   },
+
+  getFrameDetail(id: string) {
+    return this.request("/h5/detail/" + id, {
+      method: "GET",
+      params: { isSys: true },
+    });
+  },
 });

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

@@ -22,6 +22,7 @@ import { manualActions } from "./actions/editWithManualHistory";
 import { wxController } from "@/controllers/wxController";
 import { ImageCropperCtrl } from "../controllers/CropperCtrl";
 import { MediaCtrl } from "../controllers/MediaCtrl/indext";
+import { FrameControl } from "../controllers/FrameCtrl";
 
 export class EditorModule extends ModuleRoot {
   config = this.setConfig({
@@ -42,7 +43,7 @@ export class EditorModule extends ModuleRoot {
     transform: (state) => createProxy(state),
   });
   helper = this.createHelper([helpers, editHelpers]);
-    
+
   controls = {
     uploader: new UploadController({
       httpConfig: {
@@ -59,6 +60,7 @@ export class EditorModule extends ModuleRoot {
     historyCtrl: new HistoryCtrl(this),
     pickCtrl: new ImagePickController(),
     compUICtrl: new CompUICtrl(this),
+    frameControl: new FrameControl(this),
     selectCtrl: new SelectCtrl(this),
     cropCtrl: new ImageCropperCtrl(this),
     mediaCtrl: new MediaCtrl(this),