Kaynağa Gözat

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

qinyan 1 yıl önce
ebeveyn
işleme
20ac643ae9

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 14 - 17
src/modules/editor/components/CompUI/basicUI/Text/TextToolbar.tsx

@@ -9,11 +9,11 @@ import { DesignComp } from "@/modules/editor/objects/DesignTemp/DesignComp";
 import { LinkOutlined } from "@ant-design/icons-vue";
 
 import { css } from "@linaria/core";
-import { Button, Divider } from "ant-design-vue";
+import { Divider } from "ant-design-vue";
 import { defineComponent } from "vue";
 import { any } from "vue-types";
 
-import ToolbarsUI from "./TextToolbarUI";
+import TextToolbarsUI from "./TextToolbarUI";
 import {
   AlignComp,
   FontFamily,
@@ -127,6 +127,10 @@ export const TextToolbar = defineComponent({
         component: (props: any) => (
           <LinkButton icon={<LinkOutlined />} {...props} />
         ),
+        changeExtra: (record: any) => {
+          record.value = record.value.value;
+          return record;
+        },
         itemProps: {
           class: "!mx-2px",
         },
@@ -142,30 +146,23 @@ export const TextToolbar = defineComponent({
     ];
     const changeVal = (e: { dataIndex: string; value: any }) => {
       const editor = controls.textEditor;
-      console.log(e);
       if (!editor) {
         return;
       }
-      // const command = editor ? editor.commands.get(e.dataIndex) : null;
-      // console.log(e, command);
-
-      if (e.dataIndex == "link") {
-        editor.execute(e.dataIndex, e.value);
-      } else {
-        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);
+      editor.execute(e.dataIndex, e.value);
+      console.log("change", e);
+      setTimeout(() => {
+        const selection = window.getSelection();
+        selection?.removeAllRanges();
+        editor.editing.view.focus();
+      }, 100);
     };
     return () => {
       const { component } = props;
       return (
         <div class={[TextToolbarStyle, "flex items-center"]} id="text_toolbar">
-          <ToolbarsUI
+          <TextToolbarsUI
             editor={controls.textEditor}
-            data={component}
             columns={toolbarColumns}
             onChange={changeVal}
           />

+ 91 - 97
src/modules/editor/components/CompUI/basicUI/Text/TextToolbarUI.tsx

@@ -1,32 +1,23 @@
-import { css, cx } from "@linaria/core";
+import { css } from "@linaria/core";
 import { Tooltip } from "ant-design-vue";
-import _ from "lodash";
-import { computed, defineComponent } from "vue";
-import { any, array, bool, func } from "vue-types";
+import { defineComponent, reactive, onMounted, onUnmounted } from "vue";
+import { any, array, func, number, object } from "vue-types";
 
 export interface ColumnItem {
   label?: string;
   component?: ((...args: any[]) => any) | Record<string, any>;
   dataIndex?: string;
-  setterIndex?: string;
   props?: { [name: string]: any };
   itemProps?: { [name: string]: any };
-  getValue?: (v: any, data?: any) => any;
-  isDisable?: (value: any, data: any) => boolean;
-  isLoading?: (value: any, data: any) => boolean;
-  isVisible?: (value: any, data: any) => boolean;
   changeExtra?: (data: any) => any;
-  children?: ColumnItem[];
 }
 
 export default defineComponent({
   props: {
     columns: array<ColumnItem>().isRequired,
     editor: any(),
-    data: any().isRequired,
-    disabled: bool(),
+    data: any(),
     onChange: func(),
-    onChangeEnd: func(),
   },
   setup(props) {
     return () => <FormUI {...props} />;
@@ -35,11 +26,8 @@ export default defineComponent({
 
 const FormUI = (props: {
   columns: ColumnItem[];
-  data: any;
   editor: any;
-  disabled?: boolean;
   onChange?: (...arg: any) => void;
-  onChangeEnd?: (...arg: any) => void;
 }) => {
   const { columns, ...restProps } = props;
   return (
@@ -48,7 +36,7 @@ const FormUI = (props: {
         if (!column.dataIndex) {
           return renderUI({ props: restProps, column, index });
         }
-        return renderFormItem({ column, ...restProps, index });
+        return <RenderFormItem column={column} index={index} {...restProps} />;
       })}
     </>
   );
@@ -73,89 +61,95 @@ const renderUI = ({ props, column, index }: any) => {
   }
 };
 
-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 editor = props.editor;
-  const compValue = editor ? editor.commands.get(column.dataIndex) : "";
-  // console.log(column.dataIndex, compValue.value);
-
-  // const compValue = computed(() => {
-  //   const { data, column } = props;
-  //   if (!column.dataIndex) return;
-  //   const itemValue = _.get(data, column.dataIndex);
-  //   return column.getValue ? column.getValue(itemValue, data) : itemValue;
-  // });
-
-  const changeVal = (value: any, ...args: any[]) => {
-    const { column } = props;
-    let params = {
-      dataIndex: column.dataIndex,
-      setterIndex: column.setterIndex,
-      value,
-      ...args,
+export const RenderFormItem = defineComponent({
+  props: {
+    column: object<ColumnItem>(),
+    index: number(),
+    editor: any(),
+    onChange: func(),
+    onChangeEnd: func(),
+  },
+  setup(props) {
+    const state = reactive({
+      value: undefined,
+    });
+    function handleValueChange() {
+      const { column, editor } = props;
+      const command = editor ? editor.commands.get(column?.dataIndex) : "";
+      if (command) {
+        console.log("change==>", column?.dataIndex, state.value);
+        state.value = command.value;
+      }
+    }
+    const initCommands = () => {
+      const { column, editor } = props;
+      const command = editor ? editor.commands.get(column?.dataIndex) : "";
+      if (command) {
+        state.value = command.value;
+
+        command.on("change:value", handleValueChange);
+      }
+    };
+    onMounted(() => {
+      initCommands();
+    });
+    onUnmounted(() => {
+      const { column, editor } = props;
+      const command = editor ? editor.commands.get(column?.dataIndex) : "";
+      if (command) {
+        command.off("change:value", handleValueChange);
+      }
+    });
+
+    const changeVal = (value: any, ...args: any[]) => {
+      const { column } = props;
+      let params = {
+        dataIndex: column?.dataIndex,
+        value: { value },
+        ...args,
+      };
+      if (column?.changeExtra) params = column.changeExtra?.(params);
+      props.onChange?.(params);
+      return params;
     };
-    if (column.changeExtra) params = column.changeExtra?.(params);
-    onChange?.(params);
-    return params;
-  };
-
-  const changeValEnd = (value: any, ...args: any[]) => {
-    const params = changeVal(value, ...args);
-    onChangeEnd?.(params);
-  };
-
-  // const isVisible = column.isVisible?.(compValue.value, data);
-  // if (column.isVisible && !isVisible) return null;
-
-  // const disabled = props.disabled || column.isDisable?.(compValue.value, data);
 
-  const component = column.component;
+    const changeValEnd = (value: any, ...args: any[]) => {
+      const params = changeVal(value, ...args);
+      props.onChangeEnd?.(params);
+    };
 
-  return (
-    <div
-      key={index}
-      class={formItemStyles}
-      {...column.itemProps}
-      onClick={(e) => e.stopPropagation()}
-    >
-      {column.label ? (
-        <Tooltip title={column.label} placement="top">
-          <component
-            value={compValue.value}
-            {...column.props}
-            loading={column.isLoading?.(compValue.value, data)}
-            onChange={changeVal}
-            onChangeEnd={changeValEnd}
-          />
-        </Tooltip>
-      ) : (
-        <component
-          value={compValue.value}
-          {...column.props}
-          loading={column.isLoading?.(compValue.value, data)}
-          onChange={changeVal}
-          onChangeEnd={changeValEnd}
-        />
-      )}
-    </div>
-  );
-};
+    const component = props.column?.component || number;
+    return () => {
+      const { column, index } = props;
+      return (
+        <div
+          key={index}
+          class={formItemStyles}
+          {...column?.itemProps}
+          onClick={(e) => e.stopPropagation()}
+        >
+          {column?.label ? (
+            <Tooltip title={column.label} placement="top">
+              <component
+                value={state.value}
+                {...column.props}
+                onChange={changeVal}
+                onChangeEnd={changeValEnd}
+              />
+            </Tooltip>
+          ) : (
+            <component
+              value={state.value}
+              {...column?.props}
+              onChange={changeVal}
+              onChangeEnd={changeValEnd}
+            />
+          )}
+        </div>
+      );
+    };
+  },
+});
 
 const formItemStyles = css`
   height: 100%;

+ 56 - 42
src/modules/editor/components/CompUI/basicUI/Text/ToolbarComp.tsx

@@ -8,12 +8,12 @@ import {
 import { css } from "@linaria/core";
 import { Button, Dropdown, InputNumber, Menu, Tooltip } from "ant-design-vue";
 
+import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select";
 import Pickr from "@simonwep/pickr";
 import "@simonwep/pickr/dist/themes/nano.min.css";
-import { defineComponent, onMounted, reactive, watch } from "vue";
-import { any, string } from "vue-types";
-import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select";
 import { queenApi } from "queenjs";
+import { defineComponent, onMounted, ref, watch, onUnmounted } from "vue";
+import { any, bool, string } from "vue-types";
 
 export const TextColor = defineComponent({
   props: {
@@ -22,7 +22,7 @@ export const TextColor = defineComponent({
   emits: ["change"],
   setup(props, { emit }) {
     let picker: any = null;
-
+    let emitFlagRef = ref(true);
     function initPicker() {
       picker = Pickr.create({
         el: ".color_picker",
@@ -31,7 +31,6 @@ export const TextColor = defineComponent({
         i18n: {
           "btn:save": "确定",
         },
-        // swatches: defaultColor,
         components: {
           preview: true,
           opacity: false,
@@ -45,26 +44,32 @@ export const TextColor = defineComponent({
         },
       });
 
-      // picker.on("change", (color: any) => {
-      //   const hexa = color.toHEXA().toString();
-      //   console.log("change", hexa);
-      //   // emit("change", hexa);
-      // });
       picker.on("save", (color: any) => {
         picker.hide();
         const hexa = color.toHEXA().toString();
+        if (!emitFlagRef.value) {
+          emitFlagRef.value = true;
+          return;
+        }
         emit("change", hexa);
       });
     }
     watch(
       () => props.value,
       () => {
+        emitFlagRef.value = false;
         picker.setColor(props.value);
       }
     );
     onMounted(() => {
       initPicker();
     });
+    onUnmounted(() => {
+      if (picker) {
+        picker.destroy();
+        picker = null;
+      }
+    });
 
     return () => (
       <div
@@ -135,7 +140,12 @@ export const AlignComp = defineComponent({
       return item ? item.icon : null;
     };
     return () => (
-      <Dropdown overlay={overlay()} trigger={"click"} placement="bottom">
+      <Dropdown
+        overlay={overlay()}
+        overlayClassName={"editor_toolbar_drop"}
+        trigger={"click"}
+        placement="bottom"
+      >
         <Button type="text" icon={currIcon(props.value)}></Button>
       </Dropdown>
     );
@@ -170,7 +180,12 @@ export const LineHeightComp = defineComponent({
     };
 
     return () => (
-      <Dropdown overlay={overlay()} trigger={"click"} placement="bottom">
+      <Dropdown
+        overlay={overlay()}
+        overlayClassName={"editor_toolbar_drop"}
+        trigger={"click"}
+        placement="bottom"
+      >
         <Button type="text" icon={<IconLineHeight />}></Button>
       </Dropdown>
     );
@@ -180,22 +195,17 @@ export const LineHeightComp = defineComponent({
 export const FontStyleComp = defineComponent({
   props: {
     icon: any(),
-    value: any(),
+    value: bool().def(false),
   },
   emits: ["change"],
   setup(props, { emit }) {
-    const state = reactive({
-      isOn: props.value || false,
-    });
-
     const triggerStyle = () => {
-      state.isOn = !state.isOn;
-      emit("change", state.isOn);
+      emit("change", !props.value);
     };
     return () => (
       <Button
         type="text"
-        class={state.isOn ? currStyle : null}
+        class={props.value ? currStyle : null}
         icon={props.icon}
         onClick={triggerStyle}
       ></Button>
@@ -205,7 +215,7 @@ export const FontStyleComp = defineComponent({
 
 export const FontFamily = defineComponent({
   props: {
-    value: any(),
+    value: string().def(""),
   },
   emits: ["change"],
   setup(props, { emit }) {
@@ -216,34 +226,38 @@ export const FontFamily = defineComponent({
       { label: "仿宋", value: "仿宋,FangSong,STFangsong,serif" },
       { label: "楷体", value: "楷体,KaiTi,STKaiti,sans-serif" },
     ];
-    return () => (
-      <Select
-        options={options}
-        value={props.value || ""}
-        onChange={(v) => {
-          emit("change", v);
-        }}
-      ></Select>
-    );
+    return () => {
+      return (
+        <Select
+          options={options}
+          value={props.value || ""}
+          onChange={(v) => {
+            emit("change", v);
+          }}
+        ></Select>
+      );
+    };
   },
 });
 export const FontSize = defineComponent({
   props: {
-    value: any(),
+    value: string().def("12px"),
   },
   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");
-        }}
-      />
-    );
+    return () => {
+      return (
+        <InputNumber
+          defaultValue={12}
+          min={12}
+          max={60}
+          value={parseInt(props.value) || 12}
+          onChange={(value: any) => {
+            emit("change", value + "px");
+          }}
+        />
+      );
+    };
   },
 });
 export const LinkButton = defineComponent({

+ 20 - 3
src/modules/editor/components/CompUI/basicUI/Text/component2.tsx

@@ -1,12 +1,11 @@
 import { useEditor } from "@/modules/editor";
-import HeadlessEditor from "./EditorCustom";
 import { css } from "@linaria/core";
 import { nextTick } from "process";
 import { defineComponent, onMounted, onUnmounted, reactive, ref } from "vue";
 import { string } from "vue-types";
 import { useCompData } from ".";
 import { View } from "../View";
-import { before } from "lodash";
+import HeadlessEditor from "./EditorCustom";
 
 export const Component = defineComponent({
   props: {
@@ -114,6 +113,25 @@ const EditorComp = defineComponent({
           out.stop = false;
           return out;
         }
+        const dropToolbars = document.querySelectorAll(".editor_toolbar_drop");
+        dropToolbars.forEach((e) => {
+          if (e === dom || e?.contains(dom)) {
+            out.in = true;
+            out.stop = false;
+            return out;
+          }
+        });
+        const selectToolbars = document.querySelectorAll(
+          ".ant-select-dropdown"
+        );
+        selectToolbars.forEach((e) => {
+          if (e === dom || e?.contains(dom)) {
+            out.in = true;
+            out.stop = false;
+            return out;
+          }
+        });
+
         const ckBodyWrapper = document.querySelector(".ck-body-wrapper");
         if (ckBodyWrapper === dom || ckBodyWrapper?.contains(dom)) {
           out.in = true;
@@ -193,7 +211,6 @@ const EditorComp = defineComponent({
             );
             helper.extendStreamCard(store.currStreamCardId);
             if (isChange) {
-              console.log("changing=>", isChange);
               actions.selectObjs([]);
               setTimeout(() => {
                 actions.selectObjs([props.compId]);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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