bianjiang 1 year ago
parent
commit
5f7beb8058

+ 56 - 34
src/modules/editor/components/CompUI/basicUI/Text/TextToolbar.tsx

@@ -10,54 +10,50 @@ import { LinkOutlined } from "@ant-design/icons-vue";
 
 import { css } from "@linaria/core";
 import { Button, Divider, InputNumber, Select } from "ant-design-vue";
-import { defineComponent } from "vue";
+import { defineComponent, nextTick } from "vue";
 import { any } from "vue-types";
 
 import ToolbarsUI from "../../formItems/ToolbarsUI";
-import { AlignComp, LineHeightComp, TextColor } from "./ToolbarComp";
+import {
+  AlignComp,
+  LineHeightComp,
+  TextColor,
+  FontStyleComp,
+  FontFamily,
+  FontSize,
+} from "./ToolbarComp";
 
 export const TextToolbar = defineComponent({
   props: {
     component: any<DesignComp>().isRequired,
   },
   setup(props) {
-    const { actions } = useEditor();
+    const { store, actions, controls } = useEditor();
+
     const toolbarColumns = [
       {
         dataIndex: "fontFamily",
-        component: Select,
+        component: FontFamily,
         props: {
           class: "w-180px",
-          defaultValue: "",
-          options: [
-            { label: "默认字体", value: "" },
-            { label: "宋体", value: "宋体,Songti,STSong,serif" },
-            { label: "黑体", value: "黑体,Heiti,STHeiti,sans-serif" },
-            { label: "仿宋", value: "仿宋,FangSong,STFangsong,serif" },
-            { label: "楷体", value: "楷体,KaiTi,STKaiti,sans-serif" },
-          ],
         },
       },
       {
         label: "字号",
         dataIndex: "fontSize",
-        component: InputNumber,
-        props: {
-          class: "!w-66px",
-          defaultValue: 12,
-          min: 12,
-          max: 99,
-        },
+        component: FontSize,
       },
       {
         label: "字体颜色",
-        dataIndex: "color",
+        dataIndex: "fontColor",
         component: TextColor,
       },
       {
         label: "加粗",
         dataIndex: "bold",
-        component: () => <Button icon={<IconTextBold />} type="text"></Button>,
+        component: (props: any) => (
+          <FontStyleComp icon={<IconTextBold />} {...props} />
+        ),
         itemProps: {
           class: "!mx-2px",
         },
@@ -65,8 +61,8 @@ export const TextToolbar = defineComponent({
       {
         label: "斜体",
         dataIndex: "italic",
-        component: () => (
-          <Button icon={<IconTextItalic />} type="text"></Button>
+        component: (props: any) => (
+          <FontStyleComp icon={<IconTextItalic />} {...props} />
         ),
         itemProps: {
           class: "!mx-2px",
@@ -75,8 +71,8 @@ export const TextToolbar = defineComponent({
       {
         label: "下划线",
         dataIndex: "underline",
-        component: () => (
-          <Button icon={<IconTextUnderline />} type="text"></Button>
+        component: (props: any) => (
+          <FontStyleComp icon={<IconTextUnderline />} {...props} />
         ),
         itemProps: {
           class: "!mx-2px",
@@ -85,8 +81,8 @@ export const TextToolbar = defineComponent({
       {
         label: "删除线",
         dataIndex: "strikethrough",
-        component: () => (
-          <Button icon={<IconStrikethrough />} type="text"></Button>
+        component: (props: any) => (
+          <FontStyleComp icon={<IconStrikethrough />} {...props} />
         ),
         itemProps: {
           class: "!mx-2px",
@@ -102,7 +98,7 @@ export const TextToolbar = defineComponent({
       },
       {
         label: "对齐方式",
-        dataIndex: "align",
+        dataIndex: "alignment",
         component: AlignComp,
         itemProps: {
           class: "!mx-2px",
@@ -126,22 +122,48 @@ export const TextToolbar = defineComponent({
       },
       {
         label: "链接",
-        dataIndex: "align",
-        component: () => <Button icon={<LinkOutlined />} type="text"></Button>,
+        dataIndex: "link",
+        component: (props: any) => (
+          <Button
+            icon={<LinkOutlined />}
+            type="text"
+            onClick={() => {
+              console.log(props);
+            }}
+          ></Button>
+        ),
         itemProps: {
           class: "!mx-2px",
         },
       },
+      {
+        component: () => (
+          <Divider
+            type="vertical"
+            style={{ fontSize: "26px", borderColor: "#1f1f1f" }}
+          />
+        ),
+      },
     ];
-    function changeVal(e: { dataIndex: string; value: any }) {
-      console.log(e);
+    const changeVal = (e: { dataIndex: string; value: any }) => {
+      const editor = controls.textEditor;
+      if (!editor) {
+        return;
+      }
+      // const command = editor ? editor.commands.get(e.dataIndex) : null;
+      // console.log(e, command);
+      editor.execute(e.dataIndex, { value: e.value });
+      editor.editing.view.focus();
+
+      // const command =  editor.commands.get(e.commandName)
       // actions.updateCompData(props.component, e.dataIndex, e.value);
-    }
+    };
     return () => {
       const { component } = props;
       return (
-        <div class={[TextToolbarStyle, "flex items-center"]}>
+        <div class={[TextToolbarStyle, "flex items-center"]} id="text_toolbar">
           <ToolbarsUI
+            editor={controls.textEditor}
             data={component}
             columns={toolbarColumns}
             onChange={changeVal}

+ 127 - 52
src/modules/editor/components/CompUI/basicUI/Text/ToolbarComp.tsx

@@ -1,17 +1,19 @@
 import {
+  IconLineHeight,
   IconTextCenter,
   IconTextJustify,
   IconTextLeft,
   IconTextRight,
-  IconLineHeight,
 } from "@/assets/icons";
 import { css } from "@linaria/core";
-import { Button, Dropdown, Menu, Tooltip } from "ant-design-vue";
+import { Button, Dropdown, InputNumber, Menu, Tooltip } from "ant-design-vue";
 
-import { defineComponent, onMounted } from "vue";
-import { string } from "vue-types";
 import Pickr from "@simonwep/pickr";
 import "@simonwep/pickr/dist/themes/nano.min.css";
+import { defineComponent, onMounted, reactive } from "vue";
+import { any, string } from "vue-types";
+import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select";
+
 export const TextColor = defineComponent({
   props: {
     value: string().def("#666666"),
@@ -19,7 +21,6 @@ export const TextColor = defineComponent({
   emits: ["change"],
   setup(props, { emit }) {
     let picker: any = null;
-
     function initPicker() {
       picker = Pickr.create({
         el: ".color_picker",
@@ -68,54 +69,7 @@ export const TextColor = defineComponent({
     );
   },
 });
-const ColorPicker = css`
-  position: relative;
-  width: 32px;
-  height: 32px;
-  border-radius: 2px;
-  cursor: pointer;
-  .pickr {
-    width: 100%;
-    height: 100%;
 
-    .pcr-button {
-      width: 100%;
-      height: 100%;
-      border: 1px solid transparent;
-    }
-    border-radius: 2px;
-    input {
-      &:focus,
-      &.pcr-active {
-        border-color: @inf-primary-color;
-        box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
-      }
-    }
-    button {
-      &:focus,
-      &.pcr-active {
-        border-color: @inf-primary-color;
-        box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
-      }
-    }
-  }
-  .pcr-app {
-    input {
-      &:focus,
-      &.pcr-active {
-        border-color: @inf-primary-color;
-        box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
-      }
-    }
-    button {
-      &:focus,
-      &.pcr-active {
-        border-color: @inf-primary-color;
-        box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
-      }
-    }
-  }
-`;
 export const AlignComp = defineComponent({
   props: {
     value: string<"left" | "right" | "center" | "justify">().def("left"),
@@ -213,6 +167,127 @@ export const LineHeightComp = defineComponent({
     );
   },
 });
+
+export const FontStyleComp = defineComponent({
+  props: {
+    icon: any(),
+    value: any(),
+  },
+  emits: ["change"],
+  setup(props, { emit }) {
+    const state = reactive({
+      isOn: props.value || false,
+    });
+    const triggerStyle = () => {
+      state.isOn = !state.isOn;
+      emit("change", state.isOn);
+    };
+    return () => (
+      <Button
+        type="text"
+        class={state.isOn ? currStyle : null}
+        icon={props.icon}
+        onClick={triggerStyle}
+      ></Button>
+    );
+  },
+});
+
+export const FontFamily = defineComponent({
+  props: {
+    value: any(),
+  },
+  emits: ["change"],
+  setup(props, { emit }) {
+    const options = [
+      { label: "默认字体", value: "" },
+      { label: "宋体", value: "宋体,Songti,STSong,serif" },
+      { label: "黑体", value: "黑体,Heiti,STHeiti,sans-serif" },
+      { label: "仿宋", value: "仿宋,FangSong,STFangsong,serif" },
+      { label: "楷体", value: "楷体,KaiTi,STKaiti,sans-serif" },
+    ];
+    return () => (
+      <Select
+        options={options}
+        value={props.value || ""}
+        onChange={(v) => {
+          emit("change", v);
+        }}
+      ></Select>
+    );
+  },
+});
+export const FontSize = defineComponent({
+  props: {
+    value: any(),
+  },
+  emits: ["change"],
+  setup(props, { emit }) {
+    return () => (
+      <InputNumber
+        defaultValue={12}
+        min={12}
+        max={60}
+        value={parseInt(props.value) || 12}
+        onChange={(value: any) => {
+          emit("change", value + "px");
+        }}
+      />
+    );
+  },
+});
 const currStyle = css`
   color: @inf-primary-color;
+  &:hover,
+  &:focus {
+    color: @inf-primary-color;
+  }
+`;
+const ColorPicker = css`
+  position: relative;
+  width: 32px;
+  height: 32px;
+  border-radius: 2px;
+  cursor: pointer;
+  .pickr {
+    width: 100%;
+    height: 100%;
+
+    .pcr-button {
+      width: 100%;
+      height: 100%;
+      border: 1px solid transparent;
+    }
+    border-radius: 2px;
+    input {
+      &:focus,
+      &.pcr-active {
+        border-color: @inf-primary-color;
+        box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
+      }
+    }
+    button {
+      &:focus,
+      &.pcr-active {
+        border-color: @inf-primary-color;
+        box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
+      }
+    }
+  }
+  .pcr-app {
+    input {
+      &:focus,
+      &.pcr-active {
+        border-color: @inf-primary-color;
+        box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
+      }
+    }
+    button {
+      &:focus,
+      &.pcr-active {
+        border-color: @inf-primary-color;
+        box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
+      }
+    }
+  }
 `;

+ 47 - 25
src/modules/editor/components/CompUI/basicUI/Text/component2.tsx

@@ -72,9 +72,9 @@ const EditorComp = defineComponent({
 
     let blurCanceler: any = null;
 
-    onUnmounted(() => {
-      blurCanceler?.();
-    });
+    // onUnmounted(() => {
+    //   blurCanceler?.();
+    // });
     const preHeight = ref<number>(0);
     const initHeight = () => {
       const dom: HTMLElement | null = document.querySelector(
@@ -102,8 +102,8 @@ const EditorComp = defineComponent({
           editorRefVal.ui.view.editable.element?.contains(dom);
         if (in1) return true;
 
-        const ckBodyWrapper = document.querySelector(".ck-body-wrapper");
-        if (ckBodyWrapper === dom || ckBodyWrapper?.contains(dom)) {
+        const toolbarWrapper = document.querySelector("#text_toolbar");
+        if (toolbarWrapper === dom || toolbarWrapper?.contains(dom)) {
           return true;
         }
       }
@@ -121,7 +121,7 @@ const EditorComp = defineComponent({
           return;
         }
         actions.submitUpdate();
-        emit("lost");
+        // emit("lost");
       }
       document.addEventListener("mousedown", blur, {
         capture: true,
@@ -134,30 +134,52 @@ const EditorComp = defineComponent({
       const dom: HTMLElement | null = document.querySelector(
         `#editor_${props.compId}`
       );
-      if (dom) {
-        editorRefVal = await HeadlessEditor.create(dom);
-        editorRefVal.setData(comp.value);
-        editorRefVal.focus();
-        const range = document.createRange();
-        range.selectNodeContents(dom);
-        const selection = window.getSelection();
-        selection?.removeAllRanges();
-        selection?.addRange(range);
-        console.log(editorRefVal);
-        editorRefVal.model.document.on("change:data", () => {
-          const value = editorRefVal?.getData();
-          console.log(value);
-          if (comp.value !== value) {
-            actions.updateCompData(comp, "value", value);
-          }
-        });
-        comp.instance = editorRefVal;
+      if (!dom) {
+        return;
       }
+      editorRefVal = await HeadlessEditor.create(dom);
+      editorRefVal.setData(comp.value);
+      editorRefVal.focus();
+      const range = document.createRange();
+      range.selectNodeContents(dom);
+      const selection = window.getSelection();
+      selection?.removeAllRanges();
+      selection?.addRange(range);
+
+      editorRefVal.model.document.on("change:data", () => {
+        const value = editorRefVal?.getData();
+        if (comp.value !== value) {
+          actions.updateCompData(comp, "value", value);
+          nextTick(() => {
+            const element = editorRefVal?.ui.view.editable.element || null;
+            if (!element) {
+              return;
+            }
+            const h = helper.pxToDesignSize(element.clientHeight);
+            const isChange = Math.abs(preHeight.value - h) > 1;
+            preHeight.value = h;
+            actions.updateCompDatas(
+              comp,
+              ["value", "layout.size.1"],
+              [value, preHeight.value]
+            );
+            helper.extendStreamCard(store.currStreamCardId);
+            if (isChange) {
+              console.log("changing=>", isChange);
+              actions.selectObjs([]);
+              setTimeout(() => {
+                actions.selectObjs([props.compId]);
+              }, 0);
+            }
+          });
+        }
+      });
+      controls.textEditor = editorRefVal;
     };
 
     onMounted(() => {
       initEditor();
-      blurCanceler = blurHandle();
+      // blurCanceler = blurHandle();
       nextTick(() => {
         initHeight();
       });

+ 17 - 13
src/modules/editor/components/CompUI/formItems/ToolbarsUI.tsx

@@ -22,6 +22,7 @@ export interface ColumnItem {
 export default defineComponent({
   props: {
     columns: array<ColumnItem>().isRequired,
+    editor: any(),
     data: any().isRequired,
     disabled: bool(),
     onChange: func(),
@@ -35,6 +36,7 @@ export default defineComponent({
 const FormUI = (props: {
   columns: ColumnItem[];
   data: any;
+  editor: any;
   disabled?: boolean;
   onChange?: (...arg: any) => void;
   onChangeEnd?: (...arg: any) => void;
@@ -75,19 +77,23 @@ export const renderFormItem = (props: {
   column: ColumnItem;
   index?: number;
   data: any;
+  editor: any;
   disabled?: boolean;
   onChange?: (...arg: any) => void;
   onChangeEnd?: (...arg: any) => void;
 }) => {
   const { column, data, index, onChange, onChangeEnd } = props;
 
-  const compValue = computed(() => {
-    const { data, column } = props;
-    if (!column.dataIndex) return;
-    const itemValue = _.get(data, column.dataIndex);
-    return column.getValue ? column.getValue(itemValue) : itemValue;
-  });
-
+  // const compValue = computed(() => {
+  //   const { data, column } = props;
+  //   if (!column.dataIndex) return;
+  //   const itemValue = _.get(data, column.dataIndex);
+  //   return column.getValue ? column.getValue(itemValue) : itemValue;
+  // });
+  const editor = props.editor;
+  const compValue = editor ? editor.commands.get(column.dataIndex) : "";
+  console.log(column.dataIndex, compValue.value);
+  
   const changeVal = (value: any, ...args: any[]) => {
     const { column } = props;
     let params = {
@@ -106,17 +112,17 @@ export const renderFormItem = (props: {
     onChangeEnd?.(params);
   };
 
-  const isVisible = column.isVisible?.(compValue.value, data);
-  if (column.isVisible && !isVisible) return null;
+  // const isVisible = column.isVisible?.(compValue.value, data);
+  // if (column.isVisible && !isVisible) return null;
 
-  const disabled = props.disabled || column.isDisable?.(compValue.value, data);
+  // const disabled = props.disabled || column.isDisable?.(compValue.value, data);
 
   const component = column.component;
 
   return (
     <div
       key={index}
-      class={cx(formItemStyles, disabled && "disabled")}
+      class={formItemStyles}
       {...column.itemProps}
       onClick={(e) => e.stopPropagation()}
     >
@@ -125,7 +131,6 @@ export const renderFormItem = (props: {
           <component
             value={compValue.value}
             {...column.props}
-            disabled={disabled}
             loading={column.isLoading?.(compValue.value, data)}
             onChange={changeVal}
             onChangeEnd={changeValEnd}
@@ -135,7 +140,6 @@ export const renderFormItem = (props: {
         <component
           value={compValue.value}
           {...column.props}
-          disabled={disabled}
           loading={column.isLoading?.(compValue.value, data)}
           onChange={changeVal}
           onChangeEnd={changeValEnd}

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

@@ -64,6 +64,7 @@ export class EditorModule extends ModuleRoot {
     selectCtrl: new SelectCtrl(this),
     cropCtrl: new ImageCropperCtrl(this),
     mediaCtrl: new MediaCtrl(this),
+    textEditor: null as any,
   };
   compObjsMap = new Map<string, CompObject>();
 

+ 27 - 28
src/modules/editor/module/stores/index.ts

@@ -119,37 +119,36 @@ export const store = EditorModule.store({
       return compId;
     },
 
-    addUserCard(detail:any) {
-        const { compMap } = this.store.designData;
-        const idMap = new Map<string, string>();
-        const nextCompMap: Record<string, DesignComp> = {};
-        Object.entries(detail.compMap as Record<string, DesignComp>).forEach(
-          ([key, comp]) => {
-            if (key === "root") {
-              idMap.set(key, nanoid());
-              comp.title = detail.title;
-              comp.thumbnail = detail.thumbnail;
-            }
-            const id = idMap.get(key) || nanoid();
-            idMap.set(key, id);
-            comp.id = id;
-            eachValuesAndPathsDeep(
-              comp.children,
-              (v) => typeof v === "string",
-              (v, paths) => {
-                const id = idMap.get(v) || nanoid();
-                idMap.set(v, id);
-                set(comp.children, paths, id);
-              }
-            );
-            nextCompMap[id] = new DesignComp(comp);
+    addUserCard(detail: any) {
+      const { compMap } = this.store.designData;
+      const idMap = new Map<string, string>();
+      const nextCompMap: Record<string, DesignComp> = {};
+      Object.entries(detail.compMap as Record<string, DesignComp>).forEach(
+        ([key, comp]) => {
+          if (key === "root") {
+            idMap.set(key, nanoid());
+            comp.title = detail.title;
+            comp.thumbnail = detail.thumbnail;
           }
-        );
-        Object.assign(compMap, nextCompMap);
-        return nextCompMap[idMap.get("root") as string];
+          const id = idMap.get(key) || nanoid();
+          idMap.set(key, id);
+          comp.id = id;
+          eachValuesAndPathsDeep(
+            comp.children,
+            (v) => typeof v === "string",
+            (v, paths) => {
+              const id = idMap.get(v) || nanoid();
+              idMap.set(v, id);
+              set(comp.children, paths, id);
+            }
+          );
+          nextCompMap[id] = new DesignComp(comp);
+        }
+      );
+      Object.assign(compMap, nextCompMap);
+      return nextCompMap[idMap.get("root") as string];
     },
 
-
     setCurrComp(compId: string) {
       this.store.currCompId = compId;
       const comps = this.helper.getCompTrees(compId);

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

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

+ 7 - 8
src/modules/editor/objects/Toolbars/text.ts

@@ -1,13 +1,12 @@
 import { createToolbars } from "./default";
 import { Toolbar } from "@/modules/editor/components/CompUI/basicUI/Text";
 
-export const TextToolbar = createToolbars( {
-    editor: {
-        component: Toolbar,
-        getVisible: (comp) =>  !!comp && comp.compKey == "Text",
-        onClick(comp) {
-            // this.actions.setCompLayer(comp, -1);
-        },
+export const TextToolbar = createToolbars({
+  editor: {
+    component: Toolbar,
+    getVisible: (comp) => !!comp && comp.compKey == "Text",
+    onClick(comp) {
+      // this.actions.setCompLayer(comp, -1);
     },
+  },
 });
-