|
|
@@ -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">
|