zhuf 3 months ago
parent
commit
5dee5972ef

+ 4 - 4
index.html

@@ -13,8 +13,8 @@
 </head>
 
 <body class="font-sans dark:text-white dark:bg-hex-121212">
-  <!-- <div id="app"></div> -->
-  <div id="bot"></div>
+  <div id="app"></div>
+  <!-- <div id="bot"></div> -->
   <noscript>
     <div>Please enable JavaScript to use this application.</div>
   </noscript>
@@ -27,8 +27,8 @@
     })()
   </script>
   <script src="/config.js"></script>
-  <!-- <script type="module" src="/src/main.ts"></script> -->
-  <script type="module" src="/src/bot.ts"></script>
+  <script type="module" src="/src/main.ts"></script>
+  <!-- <script type="module" src="/src/bot.ts"></script> -->
 </body>
 
 </html>

+ 1 - 0
package.json

@@ -23,6 +23,7 @@
     "marked": "^11.1.1",
     "pinia": "^2.0.35",
     "pinia-plugin-persist": "^1.0.0",
+    "pptxgenjs": "^3.12.0",
     "qrcode.vue": "^3.4.1",
     "sass": "1.56.2",
     "vue": "^3.2.47",

File diff suppressed because it is too large
+ 5821 - 5026
pnpm-lock.yaml


+ 6 - 4
src/App.vue

@@ -1,6 +1,8 @@
 <template>
-  <main class="h-full" font-sans p="x-4 y-10" text="center gray-700 dark:gray-200">
-    <RouterView />
-    <!-- <TheFooter /> -->
-  </main>
+  <el-config-provider namespace="ep">
+    <main class="h-full" font-sans p="x-4 y-10" text="center gray-700 dark:gray-200">
+      <RouterView />
+      <!-- <TheFooter /> -->
+    </main>
+  </el-config-provider>
 </template>

+ 23 - 29
src/components/chat-bot/index.vue

@@ -82,7 +82,7 @@ async function handleSendMessage(q?: string, isInput?: boolean) {
   chatList.value.push({
     left: false,
     name: '我',
-    d: encodeURIComponent(q),
+    d: (q),
     t,
   })
   nextTick(() => {
@@ -136,6 +136,8 @@ async function handleSendMessage(q?: string, isInput?: boolean) {
     name: '智能备课助手',
     d: '思考中',
     t: t + 1,
+    q,
+    res: undefined,
   })
   // bigModel.onWillResultChange = (resultData) => {
   //   chatList.value[i - 1].d += encodeURIComponent(resultData)
@@ -145,9 +147,12 @@ async function handleSendMessage(q?: string, isInput?: boolean) {
   // }
   bigModel.onWillResultFinish = (resultData) => {
     chatList.value[i - 1].d = ''
+    chatList.value[i - 1].res = resultData
 
-    console.log('handleStartAudioTts', resultData)
-    const fullAnswerList = resultData.match(/.{1,3}/g) ?? []
+    // console.log('handleStartAudioTts', resultData)
+    // window.str = resultData.replace(/\n/g, '<br>')
+
+    const fullAnswerList = resultData.replace(/\n/g, '<br>').match(/.{1,3}/g) ?? []
     const timer = setInterval(() => {
       if (fullAnswerList.length === 0) {
         clearInterval(timer)
@@ -155,7 +160,8 @@ async function handleSendMessage(q?: string, isInput?: boolean) {
         return
       }
       const item = fullAnswerList!.shift()
-      chatList.value[i - 1].d += encodeURIComponent(item)
+      // chatList.value[i - 1].d += encodeURIComponent(item)
+      chatList.value[i - 1].d += (item)
       nextTick(() => {
         scrollbarRef.value.setScrollTop(99999999)
       })
@@ -213,23 +219,17 @@ function handleChangeTab() {
 </script>
 
 <template>
-  <div
-    class="fixed bottom-200px right-40px h-200px w-200px flex cursor-pointer items-center justify-center"
-    @click="openDrawer"
-  >
+  <div class="fixed bottom-200px right-40px h-200px w-200px flex cursor-pointer items-center justify-center"
+    @click="openDrawer">
     <!-- <div ref="anim" /> -->
     <img :src="placeImg" alt="">
   </div>
-  <el-drawer
-    v-model="ifDrawer" direction="rtl" append-to-body :size="880" title="智能备课助手" :z-index="201"
-    style="background-color: #f0f0f0;" class="no-mb"
-  >
+  <el-drawer v-model="ifDrawer" direction="rtl" append-to-body :size="880" title="智能备课助手" :z-index="201"
+    style="background-color: #f0f0f0;" class="no-mb">
     <div class="flex">
       <div v-loading="!videoLoaded" element-loading-text="助手形象生成中..." class="h-820px w-400px">
-        <video
-          ref="videoRef" src="https://ossdownload.bozedu.net/static/webm/preview.webm "
-          class="h-full flex items-center justify-center" loop muted @loadedmetadata="handleLoadedMetadata"
-        />
+        <video ref="videoRef" src="https://ossdownload.bozedu.net/static/webm/preview.webm "
+          class="h-full flex items-center justify-center" loop muted @loadedmetadata="handleLoadedMetadata" />
       </div>
       <div class="w-440px flex flex-col justify-between rounded bg-white px-10px py-10px">
         <el-tabs v-model="modelVersion" stretch @tab-change="handleChangeTab">
@@ -243,16 +243,14 @@ function handleChangeTab() {
                 您可以试着问我:
               </div>
               <ul class="space-y-3">
-                <li
-                  v-for="item in optionInputs" :key="item"
+                <li v-for="item in optionInputs" :key="item"
                   class="flex cursor-pointer items-center justify-between rounded-16px bg-white px-18px py-8px text-12px leading-16px text-black"
-                  @click="handleSendMessage(item)"
-                >
+                  @click="handleSendMessage(item)">
                   {{ item }}
                 </li>
               </ul>
             </div>
-            <info-item v-for="item in chatList" :key="item.t" :left="item.left" :name="item.name" :d="item.d" />
+            <info-item v-for="item in chatList" :key="item.t" :left="item.left" :name="item.name" :d="item.d" :res="item.res" />
           </div>
         </el-scrollbar>
         <div class="flex items-start justify-between space-x-14px">
@@ -262,16 +260,12 @@ function handleChangeTab() {
             <Microphone class="h-20px w-20px" />
           </div> -->
           <el-tooltip class="" effect="dark" content="一次语音识别时长不能超过60秒" placement="top-start">
-            <el-button
-              :icon="Microphone" circle
+            <el-button :icon="Microphone" circle
               :color="(iatStatus === 'UNDEFINED' || iatStatus === 'CLOSED') ? '#626aef' : '#f56c6c'"
-              :disabled="isWorking" style="--color: #fff;" @click="handleStartIat"
-            />
+              :disabled="isWorking" style="--color: #fff;" @click="handleStartIat" />
           </el-tooltip>
-          <el-input
-            v-model="questionInput" size="large" type="textarea" placeholder="请输入您的问题"
-            :autosize="{ minRows: 1, maxRows: 4 }"
-          />
+          <el-input v-model="questionInput" size="large" type="textarea" placeholder="请输入您的问题"
+            :autosize="{ minRows: 1, maxRows: 4 }" />
           <el-button color="#626aef" :disabled="isWorking" @click="handleSendMessage(questionInput, true)">
             发送
           </el-button>

+ 32 - 9
src/components/chat-bot/info-item.vue

@@ -1,13 +1,35 @@
 <script setup lang="ts">
-import { marked } from 'marked'
+// import { marked } from 'marked'
+import PptxGenJS from 'pptxgenjs'
 
 const props = defineProps<{
   left: boolean
   name?: string
+  res?: string
   d: any
 }>()
 
-const showMsg = $computed(() => marked(decodeURIComponent(props.d!)))
+// const showMsg = $computed(() => marked(decodeURIComponent(props.d!)))
+const showMsg = $computed(() => (props.d!))
+
+let isWorking = ref(false)
+function downloadPptx() {
+  isWorking.value = true
+  let pptx = new PptxGenJS()
+  props.res?.split('\n\n')?.forEach((item: string) => {
+    let slide = pptx.addSlide()
+    slide.addText(item, { x: 1, y: 1, fontSize: 18, color: '363636' })
+  })
+  pptx.writeFile({ fileName: props.name + '.pptx' }).then(fileName => {
+    console.log(`created file: ${fileName}`)
+  })
+    .catch(err => {
+      console.log(`error: ${err}`)
+    }).finally(() => {
+      isWorking.value = false
+    })
+}
+
 </script>
 
 <template>
@@ -16,24 +38,25 @@ const showMsg = $computed(() => marked(decodeURIComponent(props.d!)))
       <div>{{ name }}</div>
     </div>
     <div class="r_flex-row-reverse mt-2 flex">
-      <div
-        class="text_wrapper max-w-360px min-h-44px min-w-50px rounded-3xl bg-white px-14px py-10px"
-        v-html="showMsg"
-      />
+      <div class="text_wrapper max-w-360px min-h-44px min-w-50px rounded-3xl bg-white px-14px py-10px"
+        v-html="showMsg" />
+    </div>
+    <div class="px-4 py-1">
+    <el-button @click="downloadPptx" v-if="left && res" :loading="isWorking" type="success">生成PPT</el-button>
+
     </div>
-    <!-- <el-button></el-button> -->
   </div>
 </template>
 
 <style scoped lang="scss">
-.text_wrapper  {
+.text_wrapper {
   margin: 0;
   padding: 10px;
   word-wrap: break-word;
   overflow-wrap: break-word;
   // word-break: break-all;
 
-  img{
+  img {
     display: inline-block;
     vertical-align: bottom;
     margin: 0 2px;

+ 1 - 0
src/components/chat-bot/sdk/chat.ts

@@ -147,6 +147,7 @@ export class TTSRecorder {
     }
 
     total_res = total_res + jsonData?.payload?.choices?.text?.[0]?.content
+    console.log('total_res : ', total_res)
     this.onWillResultChange && this.onWillResultChange(jsonData?.payload?.choices?.text?.[0]?.content)
 
     if (jsonData.header.code === 0 && jsonData.header.status === 2) {

+ 1 - 1
src/pages/frontpage/layout/components/appHeader/index.vue

@@ -36,7 +36,7 @@ function goBackManager() {
         <div>{{ webInfo?.js_title }}</div>
       </div>
       <div class="flex items-center space-x-4">
-        <el-avatar :size="40" :src="user?.user_avatar.middle" />
+          <el-avatar :size="40" :src="user?.user_avatar?.middle" class="max-w-40px"/>
         <el-dropdown>
           <div class="cursor-pointer text-light-50" style="color:black">
             {{ userName }}

+ 2 - 0
src/router/index.js

@@ -87,6 +87,8 @@ if (token) {
 }
 
 router.beforeEach((to, from) => {
+  // return true
+
   if (user.value?.token)
     return true
   if (!user.value?.token && to.name !== 'login' && to.name !== 'weixin-auth')