lianghongjie 1 year ago
parent
commit
258b256411
36 changed files with 400 additions and 349 deletions
  1. 11 0
      src/hooks/initRemSize.ts
  2. 0 1
      src/modules/editor/actions/edit.ts
  3. 0 16
      src/modules/editor/components/AttrsUI/CardDemo.tsx
  4. 0 7
      src/modules/editor/components/AttrsUI/Image.tsx
  5. 0 7
      src/modules/editor/components/AttrsUI/Text.tsx
  6. 0 35
      src/modules/editor/components/AttrsUI/_createAttrsHoc.tsx
  7. 0 3
      src/modules/editor/components/AttrsUI/index.ts
  8. 29 0
      src/modules/editor/components/Canvas/index.tsx
  9. 5 0
      src/modules/editor/components/CompUI/attrs.ts
  10. 0 29
      src/modules/editor/components/CompUI/baseUI/Image.tsx
  11. 0 21
      src/modules/editor/components/CompUI/baseUI/Text.tsx
  12. 0 21
      src/modules/editor/components/CompUI/baseUI/Textarea.tsx
  13. 15 0
      src/modules/editor/components/CompUI/basicUI/Image/config.ts
  14. 49 0
      src/modules/editor/components/CompUI/basicUI/Image/index.tsx
  15. 15 0
      src/modules/editor/components/CompUI/basicUI/Text/config.ts
  16. 34 16
      src/modules/editor/components/CompUI/basicUI/Text/index.tsx
  17. 29 19
      src/modules/editor/components/CompUI/basicUI/View.tsx
  18. 4 4
      src/modules/editor/components/CompUI/customUI/Card/index.tsx
  19. 31 0
      src/modules/editor/components/CompUI/customUI/CardDemo/config.ts
  20. 5 9
      src/modules/editor/components/CompUI/customUI/CardDemo/index.tsx
  21. 20 0
      src/modules/editor/components/CompUI/customUI/Cover/config.ts
  22. 21 0
      src/modules/editor/components/CompUI/customUI/Cover/index.tsx
  23. 47 0
      src/modules/editor/components/CompUI/defines/createAttrsHoc.tsx
  24. 4 4
      src/modules/editor/components/CompUI/index.ts
  25. 4 0
      src/modules/editor/components/CompUI/options.ts
  26. 0 66
      src/modules/editor/components/Viewport/Canvas/index.tsx
  27. 47 0
      src/modules/editor/components/Viewport/Content/index.tsx
  28. 11 13
      src/modules/editor/components/Viewport/Slider/SliderLeft.tsx
  29. 1 1
      src/modules/editor/components/Viewport/Slider/SliderRight.tsx
  30. 5 5
      src/modules/editor/components/Viewport/index.tsx
  31. 1 1
      src/modules/editor/components/index.ts
  32. 0 1
      src/modules/editor/config/compUIOptions/create.ts
  33. 2 66
      src/modules/editor/config/compUIOptions/index.ts
  34. 3 2
      src/modules/editor/defines/DesignTemp/DesignComp.ts
  35. 5 1
      src/modules/editor/stores/index.ts
  36. 2 1
      src/pages/editor/index.ts

+ 11 - 0
src/hooks/initRemSize.ts

@@ -0,0 +1,11 @@
+export function initRemSize() {
+  function setRem() {
+    const clientWidth = document.documentElement.clientWidth;
+    const width = clientWidth > 750 ? 375 : clientWidth;
+    const fontSize = (width / 375) * 100;
+    document.documentElement.style.fontSize = fontSize + "px";
+  }
+
+  window.addEventListener("resize", setRem);
+  setRem();
+}

+ 0 - 1
src/modules/editor/actions/edit.ts

@@ -9,7 +9,6 @@ export const editActions = EditorModule.action({
   },
   // 切换当前组件
   pickCurrComp(compId: string) {
-    if (compId === this.store.currCompId) return;
     this.store.setCurrComp(compId);
   },
   // 删除组件

+ 0 - 16
src/modules/editor/components/AttrsUI/CardDemo.tsx

@@ -1,16 +0,0 @@
-import { createAttrsHoc } from "./_createAttrsHoc";
-
-export const CardDemo = createAttrsHoc([
-  {
-    label: "标题",
-    dataIndex: "title",
-  },
-  {
-    label: "卡片数量",
-    dataIndex: "cardColumns",
-  },
-  {
-    label: "主题颜色",
-    dataIndex: "themeColor",
-  },
-]);

+ 0 - 7
src/modules/editor/components/AttrsUI/Image.tsx

@@ -1,7 +0,0 @@
-import { createAttrsHoc } from "./_createAttrsHoc";
-
-export const Image = createAttrsHoc([
-  {
-    label: "图片",
-  },
-]);

+ 0 - 7
src/modules/editor/components/AttrsUI/Text.tsx

@@ -1,7 +0,0 @@
-import { createAttrsHoc } from "./_createAttrsHoc";
-
-export const Text = createAttrsHoc([
-  {
-    label: "文本",
-  },
-]);

+ 0 - 35
src/modules/editor/components/AttrsUI/_createAttrsHoc.tsx

@@ -1,35 +0,0 @@
-import { Input } from "ant-design-vue";
-import { get } from "lodash";
-import { defineComponent } from "vue";
-import { any } from "vue-types";
-
-export function createAttrsHoc(
-  options: { label: string; dataIndex?: string }[]
-) {
-  return defineComponent({
-    props: {
-      value: any(),
-    },
-    emits: ["update:value"],
-    setup(props, { emit }) {
-      return () => (
-        <div>
-          {options.map((d) => {
-            const val = d.dataIndex
-              ? get(props.value, d.dataIndex)
-              : props.value;
-            return (
-              <div>
-                <div>{d.label}</div>
-                <Input
-                  value={val}
-                  onChange={(e) => emit("update:value", e.target.value)}
-                />
-              </div>
-            );
-          })}
-        </div>
-      );
-    },
-  });
-}

+ 0 - 3
src/modules/editor/components/AttrsUI/index.ts

@@ -1,3 +0,0 @@
-export { Image } from "./Image";
-export { Text } from "./Text";
-export { CardDemo } from "./CardDemo";

+ 29 - 0
src/modules/editor/components/Canvas/index.tsx

@@ -0,0 +1,29 @@
+import { defineUI } from "queenjs";
+import components from "..";
+import { useEditor } from "../..";
+
+export default defineUI({
+  setup() {
+    const editor = useEditor();
+    const { store } = editor;
+    return () => {
+      const { content } = store.designData;
+      return (
+        <div>
+          {content.map((d) => {
+            const Comp = components.CompUI[d.compKey];
+            return (
+              <Comp
+                key={d.id}
+                data-id={d.id}
+                {...(d.props || {})}
+                style={d.style}
+                v-model={[d.value, "value"]}
+              />
+            );
+          })}
+        </div>
+      );
+    };
+  },
+});

+ 5 - 0
src/modules/editor/components/CompUI/attrs.ts

@@ -0,0 +1,5 @@
+export { Attrs as Image } from "./basicUI/Image/config";
+export { Attrs as Text } from "./basicUI/Text/config";
+export { Attrs as CardDemo } from "./customUI/CardDemo/config";
+export { Attrs as Cover } from "./customUI/Cover/config";
+

+ 0 - 29
src/modules/editor/components/CompUI/baseUI/Image.tsx

@@ -1,29 +0,0 @@
-import { defineComponent } from "vue";
-import { string } from "vue-types";
-import { useEditor } from "../../..";
-import { View } from "./View";
-
-const imgDef = require("@/assets/imgs/default.png");
-
-export const Image = defineComponent({
-  props: {
-    value: string(),
-  },
-  emits: ["update:value"],
-  setup(props, { emit }) {
-    const { store } = useEditor();
-    async function changeVal() {
-      alert("选择模型");
-      emit("update:value", Math.random().toString());
-    }
-    return () => (
-      <View>
-        <img
-          class="w-1/1 h-1/1"
-          src={props.value || imgDef}
-          onClick={store.isEditMode? changeVal : undefined}
-        />
-      </View>
-    );
-  },
-});

+ 0 - 21
src/modules/editor/components/CompUI/baseUI/Text.tsx

@@ -1,21 +0,0 @@
-import { defineComponent } from "vue";
-import { string } from "vue-types";
-import { CkEditor } from "./CkEditor";
-import { View } from "./View";
-
-export const Text = defineComponent({
-  props: {
-    value: string(),
-  },
-  emits: ["update:value"],
-  setup(props, { emit }) {
-    return () => (
-      <View>
-        <CkEditor
-          value={props.value}
-          onChange={(v) => emit("update:value", v)}
-        />
-      </View>
-    );
-  },
-});

+ 0 - 21
src/modules/editor/components/CompUI/baseUI/Textarea.tsx

@@ -1,21 +0,0 @@
-import { defineComponent } from "vue";
-import { string } from "vue-types";
-import { CkEditor } from "./CkEditor";
-import { View } from "./View";
-
-export const Textarea = defineComponent({
-  props: {
-    value: string().def(""),
-  },
-  emits: ["update:value"],
-  setup(props, { emit }) {
-    return () => (
-      <View>
-        <CkEditor
-          value={props.value}
-          onChange={(v) => emit("update:value", v)}
-        />
-      </View>
-    );
-  },
-});

+ 15 - 0
src/modules/editor/components/CompUI/basicUI/Image/config.ts

@@ -0,0 +1,15 @@
+import { createAttrsHoc } from "../../defines/createAttrsHoc";
+
+export const defaultValue = require("@/assets/imgs/default.png");
+
+export const dragOptions = {
+  name: "图片",
+  defaultValue,
+};
+
+export const Attrs = createAttrsHoc([
+  {
+    label: "图片",
+    dataIndex: "value",
+  },
+]);

+ 49 - 0
src/modules/editor/components/CompUI/basicUI/Image/index.tsx

@@ -0,0 +1,49 @@
+import { css } from "@linaria/core";
+import { queenApi } from "queenjs";
+import { defineComponent } from "vue";
+import { string } from "vue-types";
+import { useEditor } from "../../../..";
+import { View } from "../View";
+
+export const Image = defineComponent({
+  props: {
+    value: string().def(""),
+  },
+  emits: ["update:value"],
+  setup(props, { emit }) {
+    const { store } = useEditor();
+    async function changeVal() {
+      const files = await queenApi.selectFile();
+      emit("update:value", URL.createObjectURL(files[0]));
+    }
+    return () => (
+      <View>
+        <img
+          class="w-1/1 h-1/1"
+          src={props.value}
+          onClick={store.isEditMode ? changeVal : undefined}
+        />
+        {store.isEditMode && <div class={btnStyle}>替换</div>}
+      </View>
+    );
+  },
+});
+
+const btnStyle = css`
+  position: absolute;
+  display: none;
+  top: 50%;
+  left: 50%;
+  width: 0.6rem;
+  height: 0.6rem;
+  line-height: 0.6rem;
+  text-align: center;
+  border-radius: 50%;
+  background-color: rgba(0, 0, 0, 0.5);
+  transform: translate(-50%, -50%);
+  cursor: pointer;
+
+  &:hover {
+    display: block;
+  }
+`;

+ 15 - 0
src/modules/editor/components/CompUI/basicUI/Text/config.ts

@@ -0,0 +1,15 @@
+import { createAttrsHoc } from "../../defines/createAttrsHoc";
+
+export const defaultValue = "请输入内容";
+
+export const dragOptions = {
+  name: "文本",
+  defaultValue,
+};
+
+export const Attrs = createAttrsHoc([
+  {
+    label: "文本",
+    dataIndex: "value",
+  },
+]);

+ 34 - 16
src/modules/editor/components/CompUI/baseUI/CkEditor.tsx → src/modules/editor/components/CompUI/basicUI/Text/index.tsx

@@ -1,19 +1,21 @@
 import { useEditor } from "@/modules/editor";
+import { Alignment } from "@ckeditor/ckeditor5-alignment";
 import { Bold, Italic } from "@ckeditor/ckeditor5-basic-styles";
 import { InlineEditor } from "@ckeditor/ckeditor5-editor-inline";
 import { Essentials } from "@ckeditor/ckeditor5-essentials";
-import { Alignment } from "@ckeditor/ckeditor5-alignment";
 import { FontFamily, FontSize } from "@ckeditor/ckeditor5-font";
 import { Link } from "@ckeditor/ckeditor5-link";
 import { Paragraph } from "@ckeditor/ckeditor5-paragraph";
 import { defineComponent } from "vue";
 import { string } from "vue-types";
+import { View } from "../View";
+import { css } from "@linaria/core";
 
-export const CkEditor = defineComponent({
+export const Text = defineComponent({
   props: {
-    value: string().def("请输入文本"),
+    value: string().def(""),
   },
-  emits: ["change"],
+  emits: ["update:value"],
   setup(props, { emit }) {
     const { store } = useEditor();
     const config = {
@@ -47,19 +49,35 @@ export const CkEditor = defineComponent({
       },
     };
     return () => (
-      <ckeditor
-        editor={InlineEditor}
-        onBlur={(e: any, editor: InlineEditor) =>
-          emit("change", editor.getData())
-        }
-        onReady={(editor: InlineEditor) => {
-          editor.setData(props.value);
-          if (!store.isEditMode) {
-            editor.enableReadOnlyMode("editor");
+      <View>
+        <ckeditor
+          class={textStyle}
+          editor={InlineEditor}
+          onBlur={(e: any, editor: InlineEditor) =>
+            emit("update:value", editor.getData())
           }
-        }}
-        config={config}
-      />
+          onReady={(editor: InlineEditor) => {
+            editor.setData(props.value);
+            if (!store.isEditMode) {
+              editor.enableReadOnlyMode("editor");
+            }
+          }}
+          config={config}
+        />
+      </View>
     );
   },
 });
+
+const textStyle = css`
+  p {
+    margin: 0;
+  }
+  &.ck.ck-editor__editable_inline {
+    > :last-child,
+    > :first-child {
+      margin-top: 0;
+      margin-bottom: 0;
+    }
+  }
+`;

+ 29 - 19
src/modules/editor/components/CompUI/baseUI/View.tsx → src/modules/editor/components/CompUI/basicUI/View.tsx

@@ -1,8 +1,12 @@
-import { useEditor } from "@/modules/editor";
 import { css } from "@linaria/core";
 import { defineComponent, onMounted, reactive, ref } from "vue";
+import { string } from "vue-types";
+import { useEditor } from "../../..";
 
 export const View = defineComponent({
+  props: {
+    bgSrc: string(),
+  },
   setup(props, { slots }) {
     const { store, actions } = useEditor();
     const viewRef = ref<HTMLElement>();
@@ -17,18 +21,27 @@ export const View = defineComponent({
       const isComp = state.compId;
       const isSelected = store.isEditMode && store.currCompId === state.compId;
 
+      const styleObj: any = {};
+      if (props.bgSrc) {
+        styleObj["--view-bg-src"] = `url(${props.bgSrc})`;
+      }
+
       return (
         <div
           ref={viewRef}
-          class={
-            store.isEditMode && [
-              isComp ? viewStyle : "view_inside",
-              isSelected && "view_selected",
-            ]
-          }
-          draggable={isSelected ? true : false}
+          class={[
+            store.isEditMode && isComp ? viewStyle : "view_inside",
+            store.isEditMode && isSelected && "view_selected",
+            props.bgSrc && viewBgStyle,
+          ]}
+          style={styleObj}
           onClick={
-            state.compId ? () => actions.pickCurrComp(state.compId) : undefined
+            state.compId
+              ? () => {
+                  if (state.compId !== store.currCompId)
+                    actions.pickCurrComp(state.compId);
+                }
+              : undefined
           }
         >
           {slots.default?.()}
@@ -38,6 +51,10 @@ export const View = defineComponent({
   },
 });
 
+const viewBgStyle = css`
+  background-image: var(--view-bg-src);
+`;
+
 const viewStyle = css`
   position: relative;
   &:hover {
@@ -57,21 +74,14 @@ const viewStyle = css`
     &::after {
       display: none;
     }
+
     .view_inside:hover {
       outline: 1px dashed @inf-primary-color;
       outline-offset: -1px;
     }
   }
 
-  .view_drager {
-    position: absolute;
-    right: 0;
-    bottom: 0;
-    width: 30px;
-    height: 30px;
-    background-color: @inf-primary-color;
-    transform: translateY(100%);
-    text-align: center;
-    z-index: 1;
+  .view_inside {
+    position: relative;
   }
 `;

+ 4 - 4
src/modules/editor/components/CompUI/customUI/Card.tsx → src/modules/editor/components/CompUI/customUI/Card/index.tsx

@@ -1,8 +1,8 @@
 import { defineComponent } from "vue";
 import { any } from "vue-types";
-import { Image } from "../baseUI/Image";
-import { Textarea } from "../baseUI/Textarea";
-import { View } from "../baseUI/View";
+import { Image } from "../../basicUI/Image";
+import { Text } from "../../basicUI/Text";
+import { View } from "../../basicUI/View";
 
 export const Card = defineComponent({
   props: {
@@ -18,7 +18,7 @@ export const Card = defineComponent({
     return () => (
       <View>
         <Image v-model={[props.value.title1, "value"]} />
-        <Textarea v-model={[props.value.title2, "value"]} />
+        <Text v-model={[props.value.title2, "value"]} />
       </View>
     );
   },

+ 31 - 0
src/modules/editor/components/CompUI/customUI/CardDemo/config.ts

@@ -0,0 +1,31 @@
+import { createAttrsHoc } from "../../defines/createAttrsHoc";
+
+export const defaultValue = {
+  cardColumns: 3,
+  themeColor: "red",
+  list: [] as { name: string; img: string; desc: string }[],
+  title: "新科技反光面料 引领潮流新风尚",
+  desc: "时尚 | 精致 | 百搭",
+  bgSrc:
+    "https://infishwaibao.oss-cn-chengdu.aliyuncs.com/release/sku3d/img/partner_bg.5e324d05.png",
+};
+
+export const dragOptions = {
+  name: "卡片",
+  defaultValue,
+};
+
+export const Attrs = createAttrsHoc([
+  {
+    label: "卡片数量",
+    dataIndex: "value.cardColumns",
+  },
+  {
+    label: "主题颜色",
+    dataIndex: "value.themeColor",
+  },
+  {
+    label: "背景图片",
+    dataIndex: "value.bgSrc",
+  },
+]);

+ 5 - 9
src/modules/editor/components/CompUI/customUI/CardDemo.tsx → src/modules/editor/components/CompUI/customUI/CardDemo/index.tsx

@@ -1,17 +1,13 @@
 import { css } from "@linaria/core";
 import { defineComponent, reactive, watch } from "vue";
 import { any } from "vue-types";
-import { Image, Text, View } from "..";
+import { Image, Text } from "../..";
+import { View } from "../../basicUI/View";
+import { defaultValue } from "./config";
 
 export const CardDemo = defineComponent({
   props: {
-    value: any<{
-      cardColumns: number;
-      themeColor: string;
-      title: string;
-      desc: string;
-      list: { name: string; img: string; desc: string }[];
-    }>().isRequired,
+    value: any<typeof defaultValue>().isRequired,
   },
   setup(props) {
     const state = reactive(props.value);
@@ -32,7 +28,7 @@ export const CardDemo = defineComponent({
     );
 
     return () => (
-      <View>
+      <View bgSrc={state.bgSrc}>
         <Text v-model={[state.title, "value"]} />
         <Text v-model={[state.desc, "value"]} />
         <div class="flex space-x-16px">

+ 20 - 0
src/modules/editor/components/CompUI/customUI/Cover/config.ts

@@ -0,0 +1,20 @@
+import { createAttrsHoc } from "../../defines/createAttrsHoc";
+
+export const defaultValue = {
+  title: "新科技反光面料 引领潮流新风尚",
+  desc: "时尚 | 精致 | 百搭",
+  bgSrc:
+    "https://infishwaibao.oss-cn-chengdu.aliyuncs.com/release/sku3d/img/partner_bg.5e324d05.png",
+};
+
+export const dragOptions = {
+  name: "封面",
+  defaultValue,
+};
+
+export const Attrs = createAttrsHoc([
+  {
+    label: "背景图片",
+    dataIndex: "value.bgSrc",
+  },
+]);

+ 21 - 0
src/modules/editor/components/CompUI/customUI/Cover/index.tsx

@@ -0,0 +1,21 @@
+import { defineComponent } from "vue";
+import { any } from "vue-types";
+import { View } from "../../basicUI/View";
+import { Text } from "../../basicUI/Text";
+import { defaultValue } from "./config";
+
+export const Cover = defineComponent({
+  props: {
+    value: any<typeof defaultValue>().isRequired,
+  },
+  setup(props) {
+    return () => {
+      return (
+        <View bgSrc={props.value.bgSrc}>
+          <Text v-model={[props.value.title, "value"]} />
+          <Text v-model={[props.value.desc, "value"]} />
+        </View>
+      );
+    };
+  },
+});

+ 47 - 0
src/modules/editor/components/CompUI/defines/createAttrsHoc.tsx

@@ -0,0 +1,47 @@
+import { Input } from "ant-design-vue";
+import { get, set } from "lodash";
+import { defineComponent } from "vue";
+import { any } from "vue-types";
+
+const layoutOptions = [
+  {
+    label: "外边距",
+    dataIndex: "style.margin",
+  },
+  {
+    label: "内边距",
+    dataIndex: "style.padding",
+  },
+];
+
+export function createAttrsHoc(
+  options: { label: string; dataIndex: string }[]
+) {
+  return defineComponent({
+    props: {
+      component: any(),
+    },
+    emits: ["update:component"],
+    setup(props, { emit }) {
+      return () => (
+        <div>
+          {layoutOptions.concat(options).map((d) => {
+            const val = get(props.component, d.dataIndex);
+            return (
+              <div>
+                <div>{d.label}</div>
+                <Input
+                  value={val}
+                  onChange={(e) => {
+                    set(props.component, d.dataIndex, e.target.value);
+                    emit("update:component", props.component);
+                  }}
+                />
+              </div>
+            );
+          })}
+        </div>
+      );
+    },
+  });
+}

+ 4 - 4
src/modules/editor/components/CompUI/index.ts

@@ -1,6 +1,6 @@
-export { Image } from "./baseUI/Image";
-export { Text } from "./baseUI/Text";
-export { View } from "./baseUI/View";
-export { Textarea } from "./baseUI/Textarea";
+export { Image } from "./basicUI/Image";
+export { Text } from "./basicUI/Text";
 export { Card } from "./customUI/Card";
 export { CardDemo } from "./customUI/CardDemo";
+export { Cover } from "./customUI/Cover";
+

+ 4 - 0
src/modules/editor/components/CompUI/options.ts

@@ -0,0 +1,4 @@
+export { dragOptions as Image } from "./basicUI/Image/config";
+export { dragOptions as Text } from "./basicUI/Text/config";
+export { dragOptions as CardDemo } from "./customUI/CardDemo/config";
+export { dragOptions as Cover } from "./customUI/Cover/config";

+ 0 - 66
src/modules/editor/components/Viewport/Canvas/index.tsx

@@ -1,66 +0,0 @@
-import { useEditor } from "@/modules/editor";
-import { HotKeyCtrl } from "@/modules/editor/controllers/HotKeyCtrl";
-import { defineUI } from "queenjs";
-import { onUnmounted } from "vue";
-import { Container, Draggable } from "vue-dndrop";
-
-export default defineUI({
-  setup() {
-    const editor = useEditor();
-    const { store, components, actions } = editor;
-
-    const hotKeyCtrl = new HotKeyCtrl(editor);
-    hotKeyCtrl.init();
-    onUnmounted(() => {
-      hotKeyCtrl.destroy();
-    });
-
-    return () => {
-      const { content } = store.designData;
-      return (
-        <div class="h-1/1 text-center">
-          <div
-            class="inline-block w-375px h-750px overflow-y-auto scrollbar"
-            style={store.designData.pageStyle}
-          >
-            {store.isEditMode ? (
-              <Container
-                onDrop={(e: any) =>
-                  actions.moveComp(e.removedIndex, e.addedIndex)
-                }
-              >
-                {content.map((d) => {
-                  const Comp = components.CompUI[d.compKey];
-                  return (
-                    <Draggable key={d.id}>
-                      <Comp
-                        class="draggable-item"
-                        data-id={d.id}
-                        {...(d.props || {})}
-                        style={d.style}
-                        v-model={[d.value, "value"]}
-                      />
-                    </Draggable>
-                  );
-                })}
-              </Container>
-            ) : (
-              content.map((d) => {
-                const Comp = components.CompUI[d.compKey];
-                return (
-                  <Comp
-                    key={d.id}
-                    data-id={d.id}
-                    {...(d.props || {})}
-                    style={d.style}
-                    v-model={[d.value, "value"]}
-                  />
-                );
-              })
-            )}
-          </div>
-        </div>
-      );
-    };
-  },
-});

+ 47 - 0
src/modules/editor/components/Viewport/Content/index.tsx

@@ -0,0 +1,47 @@
+import { defineUI } from "queenjs";
+import { onUnmounted } from "vue";
+import { Container, Draggable } from "vue-dndrop";
+import { useEditor } from "../../..";
+import { HotKeyCtrl } from "../../../controllers/HotKeyCtrl";
+import Canvas from "../../Canvas";
+
+export default defineUI({
+  setup() {
+    const editor = useEditor();
+    const { store, components, actions } = editor;
+
+    const hotKeyCtrl = new HotKeyCtrl(editor);
+    hotKeyCtrl.init();
+    onUnmounted(() => {
+      hotKeyCtrl.destroy();
+    });
+
+    return () => (
+      <div class="min-h-750px bg-white">
+        {store.isEditMode ? (
+          <Container
+            style={store.designData.pageStyle}
+            onDrop={(e: any) => actions.moveComp(e.removedIndex, e.addedIndex)}
+          >
+            {store.designData.content.map((d) => {
+              const Comp = components.CompUI[d.compKey];
+              return (
+                <Draggable key={d.id}>
+                  <Comp
+                    class="draggable-item"
+                    data-id={d.id}
+                    {...(d.props || {})}
+                    style={d.style}
+                    v-model={[d.value, "value"]}
+                  />
+                </Draggable>
+              );
+            })}
+          </Container>
+        ) : (
+          <Canvas />
+        )}
+      </div>
+    );
+  },
+});

+ 11 - 13
src/modules/editor/components/Viewport/Slider/SliderLeft.tsx

@@ -18,19 +18,17 @@ export default defineUI({
             <Radio.Button>组件</Radio.Button>
           </Radio.Group>
           <div class="py-16px space-y-10px">
-            {Object.entries(editor.config.compUIOptions).map(
-              ([compKey, uiOpt], i) => {
-                return (
-                  <div
-                    class="text-center leading-50px h-50px bg-dark-50 rounded"
-                    key={i}
-                    onClick={() => addCompUI(compKey as ICompKeys)}
-                  >
-                    {uiOpt.name}
-                  </div>
-                );
-              }
-            )}
+            {Object.entries(editor.config.compUIOptions).map(([compKey, uiOpt], i) => {
+              return (
+                <div
+                  class="text-center leading-50px h-50px bg-dark-50 rounded"
+                  key={i}
+                  onClick={() => addCompUI(compKey as ICompKeys)}
+                >
+                  {uiOpt.name}
+                </div>
+              );
+            })}
           </div>
         </div>
       </div>

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

@@ -16,7 +16,7 @@ export default defineUI({
             <div>当前组件</div>
             {currComp && CurrCompAttrs && (
               <div class="py-16px space-y-10px">
-                <CurrCompAttrs v-model={[currComp.value, "value"]} />
+                <CurrCompAttrs v-model={[currComp, "component"]} />
               </div>
             )}
           </div>

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

@@ -1,5 +1,5 @@
 import { defineUI } from "queenjs";
-import Canvas from "./Canvas";
+import Content from "./Content";
 import Header from "./Header";
 import SliderLeft from "./Slider/SliderLeft";
 import SliderRight from "./Slider/SliderRight";
@@ -10,8 +10,8 @@ export default defineUI({
     Header,
     SliderLeft,
     SliderRight,
-    Canvas,
-    Toolbar
+    Content,
+    Toolbar,
   },
   setup(props, { slots }) {
     return () => (
@@ -19,9 +19,9 @@ export default defineUI({
         <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 flex-col flex-1">
+          <div class="flex-1 h-1/1 scrollbar overflow-y-auto">
             {/* <slots.Toolbar /> */}
-            <slots.Canvas class="flex-1 p-30px" />
+            <slots.Content class="w-375px mx-auto my-30px" />
           </div>
           <slots.SliderRight class="w-300px bg-component border-left !border-2px" />
         </div>

+ 1 - 1
src/modules/editor/components/index.ts

@@ -1,6 +1,6 @@
 import Viewport from "./Viewport";
 import * as CompUI from "./CompUI";
-import * as AttrsUI from "./AttrsUI";
+import * as AttrsUI from "./CompUI/attrs";
 
 export default {
   Viewport,

+ 0 - 1
src/modules/editor/config/compUIOptions/create.ts

@@ -5,7 +5,6 @@ import { ICompKeys } from "../../typings";
 type UIOptions = {
   name: string;
   component?: IComponent;
-  valueOpts: { label: string; dataIndex: string; dataType: string }[];
   defaultValue?: any;
 };
 

+ 2 - 66
src/modules/editor/config/compUIOptions/index.ts

@@ -1,68 +1,4 @@
 import { createUIOptions } from "./create";
+import * as uiOptions from "../../components/CompUI/options";
 
-export const compUIOptions = createUIOptions({
-  Text: {
-    name: "文字",
-    valueOpts: [
-      {
-        label: "文字内容",
-        dataIndex: "",
-        dataType: "text",
-      },
-    ],
-  },
-
-  Textarea: {
-    name: "富文本",
-    valueOpts: [
-      {
-        label: "内容",
-        dataIndex: "",
-        dataType: "textarea",
-      },
-    ],
-  },
-
-  Image: {
-    name: "图片",
-    valueOpts: [
-      {
-        label: "图片链接",
-        dataIndex: "",
-        dataType: "picture",
-      },
-    ],
-  },
-
-  CardDemo: {
-    name: "卡片",
-    valueOpts: [
-      {
-        label: "标题",
-        dataIndex: "title",
-        dataType: "input",
-      },
-      {
-        label: "卡片数量",
-        dataIndex: "cardColumns",
-        dataType: "number",
-      },
-      {
-        label: "主题颜色",
-        dataIndex: "themeColor",
-        dataType: "color",
-      },
-    ],
-    defaultValue: {
-      cardColumns: 3,
-      themeColor: "#ffc001",
-      title: "标题",
-      desc: "描述",
-      list: [
-        { name: "name", img: "", desc: "xxx" },
-        { name: "name", img: "", desc: "xxx" },
-        { name: "name", img: "", desc: "xxx" },
-      ],
-    },
-  },
-});
+export const compUIOptions = createUIOptions(uiOptions);

+ 3 - 2
src/modules/editor/defines/DesignTemp/DesignComp.ts

@@ -4,11 +4,12 @@ import { ICompKeys } from "../../typings";
 export class DesignComp {
   id = nanoid();
   compKey: ICompKeys = "Text";
+  value: any = undefined;
   style = {
-    margin: "12px",
+    margin: "0.12rem",
   };
-  value: any = undefined;
   props?: any;
+  background?: any;
 
   constructor(data?: Partial<DesignComp>) {
     if (!data) return;

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

@@ -1,3 +1,4 @@
+import { cloneDeep } from "lodash";
 import { EditorModule } from "..";
 import { getOption } from "../config/compUIOptions/create";
 import { DesignTemp } from "../defines/DesignTemp";
@@ -32,8 +33,11 @@ export const store = EditorModule.store({
       index || (index = this.store.designData.content.length);
       const comp = new DesignComp({
         compKey,
-        value: getOption(this.config.compUIOptions, compKey)?.defaultValue,
+        value: cloneDeep(
+          getOption(this.config.compUIOptions, compKey)?.defaultValue
+        ),
       });
+      console.log(comp);
       this.store.designData.content.splice(index, 0, comp);
       return comp;
     },

+ 2 - 1
src/pages/editor/index.ts

@@ -1,8 +1,9 @@
 import { startApp } from "@/App";
 import { initAuthDef } from "@/hooks/initAuthDef";
+import { initRemSize } from "@/hooks/initRemSize";
 import CKEditor from "@ckeditor/ckeditor5-vue";
 import router from "./router";
 
-startApp(router, [initAuthDef], (app) => {
+startApp(router, [initAuthDef, initRemSize], (app) => {
   app.use(CKEditor);
 });