|
@@ -18,44 +18,44 @@
|
|
|
<img src="https://fallfor.ai/public/img/uploads/11/img_1715399064396_1 (2).gif">
|
|
|
</span>
|
|
|
<div class="info">
|
|
|
- <div class="name">Juniper</div>
|
|
|
+ <div class="name">{{ info.characterName }}</div>
|
|
|
<div class="tags">
|
|
|
- <span class="tag">Female</span>
|
|
|
- <span class="tag">Dominant</span>
|
|
|
- <span class="tag">Submissive</span>
|
|
|
+ <span class="tag" v-for="(item, index) in info.labelArr" :key="index">
|
|
|
+ {{ item }}
|
|
|
+ </span>
|
|
|
</div>
|
|
|
- <div class="infoContent">继母会做任何事情让你接受她。</div>
|
|
|
+ <div class="infoContent">{{ info.prologue }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="chat-box">
|
|
|
- <div class="messages">
|
|
|
+ <div class="messages" ref="messages">
|
|
|
<template v-for="(item, index) in returnMessage">
|
|
|
- <div v-if="item.user == 'ai'" class="text-white mb-4 flex" :key="index">
|
|
|
+ <div v-if="item.role == 'assistant'" class="text-white mb-4 flex" :key="index">
|
|
|
<!-- ai返回的信息 -->
|
|
|
<div class="pt-2 photo">
|
|
|
<img
|
|
|
- src="@/assets/images/1.png"
|
|
|
+ src="https://fallfor.ai/public/img/uploads/11/img_1715399064396_1 (2).gif"
|
|
|
class="rounded-full w-14"
|
|
|
/>
|
|
|
</div>
|
|
|
<div class="message fex-1 ml-4 mt-2 p-2 rounded-r-md rounded-bl-md text-xs" >
|
|
|
- <div v-show="messageLoading" class="loadingMessage" >
|
|
|
- <div v-loading="messageLoading" element-loading-background="rgba(0, 0, 0, 0.0)"></div>
|
|
|
+ <div v-show="!item.content" class="loadingMessage" >
|
|
|
+ <div v-loading="!item.content" element-loading-background="rgba(0, 0, 0, 0.0)"></div>
|
|
|
</div>
|
|
|
- <p v-show="!messageLoading" >{{ item.text }}</p>
|
|
|
+ <p v-show="item.content" v-html="item.content"> </p>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 用户发送的信息 -->
|
|
|
- <div v-if="item.user == 'me'" class="text-white mb-4 flex me" :key="index">
|
|
|
+ <div v-if="item.role == 'user'" class="text-white mb-4 flex me" :key="index">
|
|
|
<div class="pt-2 photo">
|
|
|
<img
|
|
|
- src="@/assets/images/1.png"
|
|
|
+ src="@/assets/images/default_avatar_user.png"
|
|
|
class="rounded-full w-14"
|
|
|
/>
|
|
|
</div>
|
|
|
<div class="message fex-1 mr-4 mt-2 p-2 rounded-l-md rounded-br-md text-xs">
|
|
|
- <p>{{ item.text }}</p>
|
|
|
+ <p>{{ item.content }}</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -66,6 +66,7 @@
|
|
|
<span>@Leon S Kennedy - Resident Evil</span>
|
|
|
</div> -->
|
|
|
<div class="flex">
|
|
|
+ <el-button class="buttonBg1 mButton" @click="newStart" style="margin-right: 5px;" type="primary" round icon="el-icon-plus"></el-button>
|
|
|
<input
|
|
|
type="text"
|
|
|
placeholder="输入消息..."
|
|
@@ -77,6 +78,7 @@
|
|
|
<button @click="getStreamChatWithWeb" class="buttonBg1 text-white px-4 rounded-r-lg text-sm">
|
|
|
发送
|
|
|
</button>
|
|
|
+
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -88,18 +90,56 @@
|
|
|
|
|
|
<script>
|
|
|
import { streamChatWithWebApi } from "@/api/chat.js"
|
|
|
+import { detailApi } from "@/api/detail.js"
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
- messageLoading: true,
|
|
|
+ info: {},
|
|
|
+ messageLoading: false,
|
|
|
returnMessage: [],
|
|
|
content: ''
|
|
|
}
|
|
|
},
|
|
|
+ mounted() {
|
|
|
+ if (this.$route.query.characterId) {
|
|
|
+ this.getDetail(this.$route.query.characterId)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ returnMessage: {
|
|
|
+ handler(newVal, lodVal) {
|
|
|
+ let messages = this.$refs.messages
|
|
|
+ messages.scrollTop = messages.scrollHeight
|
|
|
+ },
|
|
|
+ deep: true
|
|
|
+ }
|
|
|
+ },
|
|
|
methods: {
|
|
|
+ getDetail(id) {
|
|
|
+ detailApi(id).then(res => {
|
|
|
+ console.log(res, '角色详情');
|
|
|
+ this.info = res.data
|
|
|
+ let HistoryMessage = JSON.parse(localStorage.getItem(`[${123},${this.info.id}]`));
|
|
|
+ if (HistoryMessage) {
|
|
|
+ this.returnMessage = HistoryMessage
|
|
|
+ } else {
|
|
|
+ this.returnMessage.push({
|
|
|
+ role: 'assistant',
|
|
|
+ content: this.info.firstContent
|
|
|
+ })
|
|
|
+ localStorage.setItem(`[${123},${this.info.id}]`, JSON.stringify(this.returnMessage));
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
goBack() {
|
|
|
this.$router.back()
|
|
|
},
|
|
|
+ newStart() {
|
|
|
+ // 清空历史数据
|
|
|
+ localStorage.removeItem(`[${123},${this.info.id}]`);
|
|
|
+ this.returnMessage = []
|
|
|
+ this.getDetail(this.info.id)
|
|
|
+ },
|
|
|
Enterkey(e) {
|
|
|
if (e.keyCode == 13) {
|
|
|
this.getStreamChatWithWeb()
|
|
@@ -111,19 +151,90 @@ export default {
|
|
|
return
|
|
|
}
|
|
|
this.returnMessage.push({
|
|
|
- user: 'me',
|
|
|
- text: this.content
|
|
|
+ role: 'user',
|
|
|
+ content: this.content
|
|
|
})
|
|
|
+ let HistoryMessage = JSON.parse(localStorage.getItem(`[${123},${this.info.id}]`));
|
|
|
+ // 历史记录取最新的20条传给后端
|
|
|
+ if (HistoryMessage && HistoryMessage.length > 20) {
|
|
|
+ HistoryMessage = HistoryMessage.slice(HistoryMessage.length - 1, 20)
|
|
|
+ }
|
|
|
let params = {
|
|
|
+ historyMessage: HistoryMessage || [],
|
|
|
+ characterId: this.info.id,
|
|
|
+ prompt: JSON.parse(JSON.stringify(this.content))
|
|
|
+ }
|
|
|
+ // 清空输入框的值
|
|
|
+ this.content = ''
|
|
|
+ // 新增一条ai信息
|
|
|
+ this.returnMessage.push({
|
|
|
+ role: 'assistant',
|
|
|
+ content: ''
|
|
|
+ })
|
|
|
+ let res = await streamChatWithWebApi(params)
|
|
|
+ console.log(res.data.message.content, 'res');
|
|
|
+ let content = res.data.message.content
|
|
|
+ let index = 0
|
|
|
+ let xing = 1
|
|
|
+ let messageInterval = setInterval(() => {
|
|
|
+ if (index > content.length - 1) {
|
|
|
+ console.log('结束');
|
|
|
+ // 消息全部显示后存到历史localStorage
|
|
|
+ let HistoryMessage = []
|
|
|
+ // 历史只存100条,长度超出截取最新的
|
|
|
+ if (this.returnMessage.length > 100) {
|
|
|
+ HistoryMessage = JSON.stringify(this.returnMessage.slice(this.returnMessage.length - 100, 100))
|
|
|
+ } else {
|
|
|
+ HistoryMessage = JSON.stringify(this.returnMessage)
|
|
|
+ }
|
|
|
+ localStorage.setItem(`[${123},${this.info.id}]`, HistoryMessage);
|
|
|
+
|
|
|
+ clearInterval(messageInterval)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ console.log(content[index], 'content[index]');
|
|
|
+ if (content[index] == "*") {
|
|
|
+ if (xing == 1) {
|
|
|
+ xing = 2
|
|
|
+ this.returnMessage[this.returnMessage.length - 1].content += "("
|
|
|
+ } else if (xing == 2) {
|
|
|
+ xing = 1
|
|
|
+ this.returnMessage[this.returnMessage.length - 1].content += ")"
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.returnMessage[this.returnMessage.length - 1].content += content[index]
|
|
|
+ }
|
|
|
+ index += 1
|
|
|
+ }, 50)
|
|
|
+ },
|
|
|
+ async getStreamChatWithWeb_old() {
|
|
|
+ this.messageLoading = true
|
|
|
+ if (!this.content) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.returnMessage.push({
|
|
|
+ role: 'user',
|
|
|
content: this.content
|
|
|
+ })
|
|
|
+ let HistoryMessage = JSON.parse(localStorage.getItem(`[${123},${this.info.id}]`));
|
|
|
+ // 历史记录取最新的20条传给后端
|
|
|
+ if (HistoryMessage && HistoryMessage.length > 20) {
|
|
|
+ HistoryMessage = HistoryMessage.slice(HistoryMessage.length - 1, 20)
|
|
|
+ }
|
|
|
+ let params = {
|
|
|
+ historyMessage: HistoryMessage || [],
|
|
|
+ characterId: this.info.id,
|
|
|
+ prompt: this.content
|
|
|
}
|
|
|
+ // 新增一条ai信息
|
|
|
this.returnMessage.push({
|
|
|
- user: 'ai',
|
|
|
- text: ''
|
|
|
+ role: 'assistant',
|
|
|
+ content: ''
|
|
|
})
|
|
|
let res = await streamChatWithWebApi(params)
|
|
|
+ console.log(res, 'res');
|
|
|
this.messageLoading = false
|
|
|
- // 新增一条ai信息
|
|
|
+
|
|
|
if (res.status != 200) {
|
|
|
this.$message.error(res.statusText)
|
|
|
this.returnMessage.splice(this.returnMessage.length - 1, 1)
|
|
@@ -132,21 +243,58 @@ export default {
|
|
|
// 清空输入框的值
|
|
|
this.content = ''
|
|
|
|
|
|
- console.log(res, 'res.body');
|
|
|
+ console.log(res, 'res>>>');
|
|
|
+ return
|
|
|
const reader = res.body.getReader()
|
|
|
const decoder=new TextDecoder()
|
|
|
while(1){
|
|
|
const {done, value} = await reader.read()
|
|
|
+ // console.log(done, 'done');
|
|
|
if(done){
|
|
|
+ console.log(value, 'value');
|
|
|
+ // if (typeof(value) == "undefined") {
|
|
|
+ // this.$message.error('错误')
|
|
|
+ // this.returnMessage.splice(this.returnMessage.length - 1, 1)
|
|
|
+ // }
|
|
|
+ console.log('结束');
|
|
|
+ // 消息全部显示后存到历史localStorage
|
|
|
+ let HistoryMessage = []
|
|
|
+ // 历史只存100条,长度超出截取最新的
|
|
|
+ if (this.returnMessage.length > 100) {
|
|
|
+ HistoryMessage = JSON.stringify(this.returnMessage.slice(this.returnMessage.length - 100, 100))
|
|
|
+ } else {
|
|
|
+ HistoryMessage = JSON.stringify(this.returnMessage)
|
|
|
+ }
|
|
|
+ localStorage.setItem(`[${123},${this.info.id}]`, HistoryMessage);
|
|
|
break;
|
|
|
}
|
|
|
- const txt = decoder.decode(value)
|
|
|
- console.log(txt, 'txt');
|
|
|
|
|
|
- this.returnMessage[this.returnMessage.length - 1].text += txt
|
|
|
//txt就是一个一个的字 然后添加到页面上就可以了
|
|
|
+ const txt = decoder.decode(value)
|
|
|
+ // const txt = decoder.decode(value)
|
|
|
+
|
|
|
+ let data = JSON.parse(txt).message.content
|
|
|
+ console.log(data, 'data');
|
|
|
+ // if (this.isJSON(txt) && JSON.parse(txt).code != 200) {
|
|
|
+ // let data = JSON.parse(txt)
|
|
|
+ // this.$message.error(data.msg)
|
|
|
+ // this.returnMessage.splice(this.returnMessage.length - 1, 1)
|
|
|
+ // break;
|
|
|
+ // }
|
|
|
+ this.returnMessage[this.returnMessage.length - 1].content += txt
|
|
|
}
|
|
|
- }
|
|
|
+ },
|
|
|
+ isJSON(str) {
|
|
|
+ if (typeof str == 'string') {
|
|
|
+ try {
|
|
|
+ JSON.parse(str);
|
|
|
+ return true;
|
|
|
+ } catch(e) {
|
|
|
+ // console.log(e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
@@ -282,7 +430,7 @@ export default {
|
|
|
.message {
|
|
|
background: #ffffff0f;
|
|
|
border: 1px solid #5b5b5e;
|
|
|
- max-width: calc(100% - 56px);
|
|
|
+ max-width: calc(100% - 72px);
|
|
|
// flex: 1;
|
|
|
min-width: 80px;
|
|
|
}
|
|
@@ -310,4 +458,7 @@ export default {
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
}
|
|
|
+ .mButton {
|
|
|
+ border: solid 0px;
|
|
|
+ }
|
|
|
</style>
|