Przeglądaj źródła

Merge branch 'master' of http://59.110.91.129:3000/zhangmengying/AIClass

丸子 10 miesięcy temu
rodzic
commit
66824575f9

+ 13 - 3
src/api/questions.js

@@ -42,6 +42,14 @@ export async function sendChatMessageStream (
   })
 }
 
+
+//  AI 图像生成状态的枚举
+export const AiImageStatusEnum = {
+  IN_PROGRESS: 10, // 进行中
+  SUCCESS: 20, // 已完成
+  FAIL: 30 // 已失败
+}
+
 // 生成图片
 export function CreatePainting (data){
   return axios({
@@ -51,10 +59,12 @@ export function CreatePainting (data){
   })
 }
 // 绘画
-export function CreatePaintingGetMy (data){
+export function PaintingGetMys (ids){
+  const convertedIds = ids.map(id => String(Number(id)));
+  console.log(convertedIds);
   return axios({
-    url: "bjdxWeb/ai/painting-get-my",
+    url: "bjdxWeb/ai/painting-get-mys",
     method: 'get',
-    data
+    params: { ids: convertedIds.join(',') }
   })
 }

BIN
src/assets/images/xiaozhi.png


+ 164 - 126
src/views/AIPainting.vue

@@ -17,66 +17,74 @@
         <div class="chat-dialog">
           <!-- 对话消息列表 -->
           <div class="message-list">
-            <!-- 用户消息 -->
-            <div class="user-message">生成图片</div>
-            <!-- AI生成图片对话框 -->
-            <div class="ai-message">
-              接下来我将生成四张会飞的猪的图片。画面风格是写实风,主体是一只身体肥硕、粉色皮肤、小短腿的猪,它长着两只大耳朵和一条卷曲的尾巴,正扇动着一对白色的翅膀在空中飞行。<br />
-              <div class="image-list">
-                <el-image
-                  v-for="(image, index) in srcList"
-                  :key="index"
-                  style="width: fit-content; height: 150px; margin: 10px"
-                  :src="image"
-                  :preview-src-list="srcList"
-                  fit="cover"
-                  show-progress
-                >
-                  <template
-                    #toolbar="{
-                      actions,
-                      prev,
-                      next,
-                      reset,
-                      activeIndex,
-                      setActiveItem
-                    }"
+            <div v-for="(item, index) in imageAllList" :key="index">
+              <!-- 用户消息 -->
+              <div class="user-message" v-if="item.type === 'user'">
+                {{ item.content }}
+              </div>
+              <!-- AI生成图片对话框 -->
+              <div class="ai-message" v-if="item.type !== 'user'">
+                {{ item.content }}
+                {{ item.imageList }}
+
+                <div class="image-list" v-if="item.imageList">
+                  <el-image
+                    v-for="(image, index) in item.imageList"
+                    :key="index"
+                    style="width: fit-content; height: 150px; margin: 10px"
+                    :src="image"
+                    :preview-src-list="item.imageList"
+                    fit="cover"
+                    show-progress
                   >
-                    <el-icon @click="prev"><Back /></el-icon>
-                    <el-icon @click="next"><Right /></el-icon>
-                    <el-icon @click="setActiveItem(srcList.length - 1)">
-                      <DArrowRight />
-                    </el-icon>
-                    <el-icon @click="actions('zoomOut')"><ZoomOut /></el-icon>
-                    <el-icon
-                      @click="
-                        actions('zoomIn', {
-                          enableTransition: false,
-                          zoomRate: 2
-                        })
-                      "
+                    <template
+                      #toolbar="{
+                        actions,
+                        prev,
+                        next,
+                        reset,
+                        activeIndex,
+                        setActiveItem
+                      }"
                     >
-                      <ZoomIn />
-                    </el-icon>
-                    <el-icon
-                      @click="
-                        actions('clockwise', {
-                          rotateDeg: 180,
-                          enableTransition: false
-                        })
-                      "
-                    >
-                      <RefreshRight />
-                    </el-icon>
-                    <el-icon @click="actions('anticlockwise')"
-                      ><RefreshLeft
-                    /></el-icon>
-                    <el-icon @click="reset"><Refresh /></el-icon>
-                    <el-icon @click="download(activeIndex)"
-                      ><Download
-                    /></el-icon>
-                  </template>
-                </el-image>
+                      <el-icon @click="prev"><Back /></el-icon>
+                      <el-icon @click="next"><Right /></el-icon>
+                      <el-icon
+                        @click="setActiveItem(item.imageList.length - 1)"
+                      >
+                        <DArrowRight />
+                      </el-icon>
+                      <el-icon @click="actions('zoomOut')"><ZoomOut /></el-icon>
+                      <el-icon
+                        @click="
+                          actions('zoomIn', {
+                            enableTransition: false,
+                            zoomRate: 2
+                          })
+                        "
+                      >
+                        <ZoomIn />
+                      </el-icon>
+                      <el-icon
+                        @click="
+                          actions('clockwise', {
+                            rotateDeg: 180,
+                            enableTransition: false
+                          })
+                        "
+                      >
+                        <RefreshRight />
+                      </el-icon>
+                      <el-icon @click="actions('anticlockwise')"
+                        ><RefreshLeft
+                      /></el-icon>
+                      <el-icon @click="reset"><Refresh /></el-icon>
+                      <el-icon @click="download(activeIndex)"
+                        ><Download
+                      /></el-icon>
+                    </template>
+                  </el-image>
+                </div>
               </div>
             </div>
           </div>
@@ -96,8 +104,12 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
-import { CreatePainting, CreatePaintingGetMy } from '@/api/questions.js'
+import { ref, onMounted, onUnmounted } from 'vue'
+import {
+  AiImageStatusEnum,
+  CreatePainting,
+  PaintingGetMys
+} from '@/api/questions.js'
 import { useRouter, useRoute } from 'vue-router'
 import {
   Document,
@@ -107,11 +119,6 @@ import {
   ArrowLeftBold
 } from '@element-plus/icons-vue'
 
-const myPaintings = ref([])
-
-// 消息列表
-const messageList = ref([])
-
 // 返回上一页
 const goBack = () => {
   router.go(-1)
@@ -119,60 +126,42 @@ const goBack = () => {
 const router = useRouter()
 const route = useRoute()
 
-// AI生成图片函数,传递输入的提示词
-const generatePainting = prompt => {
-  // 传递提示词参数
-  CreatePainting({
-    modelId: 56,
-    prompt,
-    width: 1024,
-    height: 1024
-  })
-    .then(res => {
-      console.log(res)
-      console.log(prompt)
-      // 添加处理响应逻辑,更新图片列表
-      // 添加消息到消息列表
-      messageList.value.push({ type: 'user', content: prompt })
-       // 响应中包含图片id
-      if (res.data && res.data.id) {
-        // 添加AI响应消息到消息列表
-        messageList.value.push({ type: 'ai', content: `生成图片成功,ID为 ${res.data.id}` })
-      }
-    })
-    .catch(error => {
-      console.error('生成图片失败:',  error)
-       messageList.value.push({ type: 'ai', content: '生成图片失败,请重试' })
-    })
-}
-
-// 修改发送消息函数,调用生成图片方法并传递提示词
-const sendMessage = () => { 
-  const prompt = inputMessage.value.trim() 
-  if (prompt) { 
-    // 直接调用 generatePainting 函数,不再需要 messages 变量
-    generatePainting(prompt) 
-    inputMessage.value = '' 
-  } 
-}
-
-// 获取绘图记录函数
-// const getMyPaintings = () => {
-//   CreatePaintingGetMy().then(res => {
-//     console.log(res);
-//     // 可添加处理响应逻辑,如更新本地数据
-//   });
-// }
-
 // 消息列表和输入内容的响应式变量
 const messages = ref([])
+
 const inputMessage = ref('')
+// 发送消息函数
+const sendMessage = () => {
+  if (inputMessage.value.trim()) {
+    messages.value.push(inputMessage.value.trim())
+    inputMessage.value = ''
 
-// 在组件挂载时获取所有绘图记录
-onMounted(() => {
-  // getPaintingRecordById()
-  generatePainting()
-})
+    let content = inputMessage.value.trim()
+    console.log('-------', content)
+    content = '给我一个小妖怪'
+    console.log('-------', content)
+
+    imageAllList.value.push({
+      type: 'user',
+      content: content
+    })
+    imageAllList.value.push({
+      type: 'ai',
+      content: '正在为您生成图片,请稍等...'
+    })
+    CreatePainting({
+      modelId: 56,
+      prompt: content,
+      width: 1024,
+      height: 1024
+    }).then(res => {
+      console.log('生成图片', res)
+      //目前写死调用已生成的图片,全部通了后再改
+      // inProgressImageMap.value[res.data] = {}
+      inProgressImageMap.value[260] = {}
+    })
+  }
+}
 
 // 生成图片
 import { ElIcon } from 'element-plus'
@@ -188,17 +177,66 @@ import {
   ZoomOut
 } from '@element-plus/icons-vue'
 
-const url =
-  'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg'
-const srcList = [
-  'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
-  'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
-  'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
-  'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
-  'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
-  'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
-  'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg'
-]
+// const url =
+//   'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg'
+// const srcList = [
+//   'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
+// ]
+
+const imageAllList = ref([]) // 对话的消息列表
+const imageList = ref([]) // image 列表
+// 图片轮询相关的参数(正在生成中的)
+const inProgressImageMap = ref({}) // 监听的 image 映射,一般是生成中(需要轮询),key 为 image 编号,value 为 image
+const inProgressTimer = ref() // 生成中的 image 定时器,轮询生成进展
+
+/** 轮询生成中的 image 列表 */
+const refreshWatchImages = async () => {
+  const imageIds = Object.keys(inProgressImageMap.value)
+  if (imageIds.length == 0) {
+    return
+  }
+  console.log('轮询生成中的 image 列表', imageIds)
+  const list = await PaintingGetMys(imageIds)
+  console.log('轮询生成中的 image 列表', list)
+  const newWatchImages = {}
+  // 添加空值检查
+  if (list.data) {
+    list.data.forEach(image => {
+      if (image.status === AiImageStatusEnum.IN_PROGRESS) {
+        newWatchImages[image.id] = image
+      } else {
+        //   const index = imageList.value.findIndex((oldImage) => image.id === oldImage.id)
+        //   if (index >= 0) {
+        // 更新 imageList
+        // imageList.value[index] = image
+        imageAllList.value.pop()
+        imageAllList.value.push({
+          type: 'ai',
+          content: '已为您生成图片:',
+          imageList: image.picUrl
+        })
+        // }
+      }
+    })
+  }
+  console.log('================', imageAllList)
+  inProgressImageMap.value = newWatchImages
+}
+
+/** 组件挂在的时候 */
+onMounted(async () => {
+  // 自动刷新 image 列表
+  inProgressTimer.value = setInterval(async () => {
+    await refreshWatchImages()
+  }, 1000 * 3)
+})
+
+/** 组件取消挂在的时候 */
+onUnmounted(async () => {
+  if (inProgressTimer.value) {
+    clearInterval(inProgressTimer.value)
+  }
+})
 </script>
 
 <style scoped lang="scss">

+ 1 - 7
src/views/AIQuestions.vue

@@ -68,13 +68,6 @@ const route = useRoute()
 const personId = ref(route.query.id)
 const personName = ref(route.query.name)
 const personIntroduce = ref(route.query.message)
-
-// 智能问答
-CreateDialogue({ id: personId.value }).then(res => {
-  console.log("创建会话:",res);
-}).catch(error => {
-  console.error('请求出错:', error);
-});
 const personImage = ref(route.query.image)
 
 // 渲染实验室携带的人物形象图片
@@ -400,6 +393,7 @@ onMounted(async () => {
   if(personId.value) {
     // 智能问答
     CreateDialogue({roleId: personId.value}).then(res => {
+      console.log("创建会话:",res);
       activeConversationId.value = res.data;
     }).catch(error => {
       console.error('请求出错:', error);