bianjiang 1 year ago
parent
commit
856a8b44d9

+ 17 - 3
src/modules/editor/components/CompUI/basicUI/Page/PageMusic.tsx

@@ -6,7 +6,14 @@ import { css } from "@linaria/core";
 import { Button, Slider } from "ant-design-vue";
 import { Howl } from "howler";
 import { nanoid } from "nanoid";
-import { defineComponent, reactive, ref, watch } from "vue";
+import {
+  defineComponent,
+  reactive,
+  ref,
+  watch,
+  onUnmounted,
+  onMounted,
+} from "vue";
 import { bool, number } from "vue-types";
 declare const WeixinJSBridge: any;
 export const PageMusic = defineComponent({
@@ -21,7 +28,6 @@ export const PageMusic = defineComponent({
     const rootComp = helper.findRootComp();
     let audioKey = nanoid();
     let audioBgm = ref();
-
     const initAudioBgm = () => {
       audioBgm.value = null;
       audioBgm.value = new Howl({
@@ -70,7 +76,7 @@ export const PageMusic = defineComponent({
         }
       });
     };
-    initAudioBgm();
+
     const playStep = () => {
       if (!audioBgm.value) {
         return;
@@ -107,6 +113,14 @@ export const PageMusic = defineComponent({
         initAudioBgm();
       }
     );
+    onMounted(() => {
+      initAudioBgm();
+    });
+    onUnmounted(() => {
+      audioRest();
+      audioBgm.value = null;
+      controls.mediaCtrl.removeMedia(audioKey);
+    });
     const seekChange = (v: number) => {
       state.currentTime = v;
       audioBgm.value && audioBgm.value.seek(v);

+ 17 - 3
src/modules/editor/components/CompUI/basicUI/Text/component.tsx

@@ -150,11 +150,27 @@ const EditorComp = defineComponent({
     let blurCanceler: any = null;
     onMounted(() => {
       blurCanceler = blurHandle();
+      nextTick(() => {
+        initHeight();
+      });
     });
     onUnmounted(() => {
       blurCanceler?.();
     });
-
+    const preHeight = ref<number>(0);
+    const initHeight = () => {
+      const h = helper.pxToDesignSize(inputRef.value?.$el.clientHeight);
+      const isChange = Math.abs(preHeight.value - h) > 1;
+      preHeight.value = h;
+      actions.updateCompData(comp, "layout.size.1", preHeight.value);
+      helper.extendStreamCard(store.currStreamCardId);
+      if (isChange) {
+        actions.selectObjs([]);
+        setTimeout(() => {
+          actions.selectObjs([props.compId]);
+        }, 0);
+      }
+    };
     function isInCkBodyWrapper(dom: HTMLElement) {
       if (editorInstance.value) {
         const in1 =
@@ -190,8 +206,6 @@ const EditorComp = defineComponent({
       };
     }
 
-    const preHeight = ref<number>(0);
-
     return () => (
       <ckeditor
         class={textStyle}

+ 164 - 13
src/modules/editor/components/Viewport/Toolbar/AiText.tsx

@@ -1,28 +1,179 @@
 import { useEditor } from "@/modules/editor";
-import { defineComponent } from "vue";
-import { Button, Input } from "ant-design-vue";
+import { CloseOutlined } from "@ant-design/icons-vue";
+import { defineComponent, reactive } from "vue";
+import { Button, Input, message } from "ant-design-vue";
+import { css } from "@linaria/core";
+import { queenApi } from "queenjs";
 export default defineComponent({
-  setup() {
-    const { store } = useEditor();
+  emits: ["visible"],
+  setup(props, { emit }) {
+    const { store, actions } = useEditor();
+    const state = reactive({
+      loading: false,
+      inputValue: "",
+      aiValue: "",
+      boxFocus: false,
+      generated: false,
+    });
+    const generateWord = () => {
+      if (state.loading) {
+        return;
+      }
+      state.loading = true;
+      const reqData = {
+        model: "gpt-3.5-turbo",
+        messages: [
+          {
+            role: "user",
+            content: state.inputValue,
+          },
+        ],
+      };
+      const xhr = new XMLHttpRequest();
+      xhr.open(
+        "post",
+        "http://186b2d5554134321a0afd4b1be443273.apig.ap-southeast-1.huaweicloudapis.com/chatgpt"
+      );
+      xhr.setRequestHeader("content-type", "application/json");
+      xhr.send(JSON.stringify(reqData));
+      xhr.onload = function (e: any) {
+        let result = e.target?.responseText;
+
+        try {
+          result = JSON.parse(result);
+          const { choices } = result;
+          const message = choices[0].message.content;
+          state.aiValue = message;
+          state.generated = true;
+        } catch (e) {
+          queenApi.messageError("生成失败!");
+          console.log(e);
+        } finally {
+          state.loading = false;
+        }
+      };
+      xhr.onerror = (e: any) => {
+        queenApi.messageError("生成失败!");
+        console.log(e);
+        state.loading = false;
+      };
+    };
+    const addText = async () => {
+      const aitext = `<p style="line-height:1.5;"><span style="font-size:14px;">${state.aiValue}</span></p>`;
+      await actions.clickCompToDesign("Text", (comp) => {
+        actions.updateCompData(comp, "value", aitext);
+      });
+    };
 
     return () => (
-      <div class="w-280px p-20px bg-component border-r-4px">
+      <div class={[AIStyle, "w-280px p-20px bg-component"]}>
         <div>
-          <div>AI提示词</div>
-          <div>
-            <Input.TextArea showCount={true} />
+          <div class={"flex justify-between items-center "}>
+            AI提示词
+            <CloseOutlined
+              onClick={() => {
+                emit("visible", false);
+              }}
+            />
+          </div>
+          <div class={"mt-14px"}>
+            <div class={["input_box pb-12px", state.boxFocus ? "focus" : ""]}>
+              <Input.TextArea
+                class={"ai_input  scrollbar"}
+                value={state.inputValue}
+                maxlength={1000}
+                onChange={(e) => {
+                  if (state.inputValue.length >= 1000) {
+                    return;
+                  }
+                  state.inputValue = e.target.value || "";
+                }}
+                onFocus={() => {
+                  state.boxFocus = true;
+                }}
+                onBlur={() => {
+                  state.boxFocus = false;
+                }}
+                autoSize={{ minRows: 3, maxRows: 6 }}
+                placeholder={"请输入关键词,AI将自动帮您生成对应文案"}
+              />
+              <div class={"px-12px text-right f-12px text-gray"}>
+                {state.inputValue.length}/1000
+              </div>
+            </div>
           </div>
         </div>
-        <div>
+        <div class={"mt-24px"}>
           <div>结果生成</div>
-          <div>
-            <Input.TextArea />
+          <div class={"mt-14px result_text"}>
+            <Input.TextArea
+              class={"ai_input  scrollbar"}
+              autoSize={{ minRows: 6, maxRows: 6 }}
+              readonly
+              value={state.aiValue}
+            />
           </div>
         </div>
-        <div>
-          <Button type="primary">开始生成</Button>
+        <div class={"mt-24px space-y-10px"}>
+          {state.generated ? (
+            <Button
+              block
+              class={"fade_input"}
+              type="primary"
+              onClick={generateWord}
+              loading={state.loading}
+            >
+              重新生成
+            </Button>
+          ) : (
+            <Button
+              block
+              type="primary"
+              onClick={generateWord}
+              loading={state.loading}
+            >
+              开始生成
+            </Button>
+          )}
+          {state.generated && (
+            <Button block type="primary" onClick={addText}>
+              添加至图层
+            </Button>
+          )}
         </div>
       </div>
     );
   },
 });
+const AIStyle = css`
+  border-radius: 4px;
+  box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.2);
+  .input_box,
+  .result_text {
+    position: relative;
+    background-color: #303030;
+    border-radius: 4px;
+
+    .ai_input {
+      font-size: 12px;
+      border-color: transparent;
+      &:hover,
+      &:focus {
+        border-color: transparent;
+        box-shadow: none;
+      }
+    }
+  }
+  .input_box {
+    border: 1px solid transparent;
+    &.focus,
+    &:hover {
+      border-color: @inf-primary-color;
+    }
+  }
+  .fade_input {
+    color: @inf-primary-color;
+    border-color: @inf-primary-fade-color;
+    background-color: @inf-primary-fade-color;
+  }
+`;

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

@@ -5,12 +5,15 @@ import { Dropdown } from "ant-design-vue";
 import { css } from "@linaria/core";
 import { useLauncher } from "@/modules/launcher";
 import AiText from "./AiText";
+import { reactive } from "vue";
 export default defineUI({
   setup() {
     const { actions, controls } = useEditor();
     const launcher = useLauncher();
     const { history } = controls.historyCtrl;
-
+    const state = reactive({
+      aiVisible: false,
+    });
     return () => (
       <>
         <div class="absolute top-20px left-20px space-x-10px z-999">
@@ -26,13 +29,25 @@ export default defineUI({
           />
         </div>
         <div class="absolute top-20px right-20px space-x-10px z-999">
-          {/* <Dropdown
-            overlay={<AiText />}
-            placement="bottomRight"
-            trigger="click"
+          <Dropdown
+            overlay={
+              <AiText
+                onVisible={(v) => {
+                  state.aiVisible = v;
+                }}
+              />
+            }
+            destroyPopupOnHide={true}
+            placement="bottom"
+            visible={state.aiVisible}
           >
-            <TipIcons.AiText class={btnCls} />
-          </Dropdown> */}
+            <TipIcons.AiText
+              class={btnCls}
+              onClick={() => {
+                state.aiVisible = !state.aiVisible;
+              }}
+            />
+          </Dropdown>
           <TipIcons.Screenshot
             class={btnCls}
             onClick={() => actions.updateThumbnailByScreenshot(true)}

+ 3 - 0
src/modules/editor/controllers/MediaCtrl/indext.ts

@@ -19,4 +19,7 @@ export class MediaCtrl extends ModuleControl<EditorModule> {
       }
     }
   }
+  removeMedia(currKey: string) {
+    this.state.medias.delete(currKey);
+  }
 }

+ 1 - 0
src/pages/website/Promotion2/controller.tsx

@@ -47,6 +47,7 @@ export function createPromotinController(
       {
         title: "编辑分享",
         width: "1000px",
+        destroyOnClose: true,
       }
     );
   }