mirror of
https://github.com/yangjian102621/geekai.git
synced 2026-04-30 15:04:30 +08:00
修改重新回答功能,撤回千面的问答内容为可编辑内容,撤回的内容不会增加额外的上下文
This commit is contained in:
@@ -29,7 +29,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content" v-html="content"></div>
|
<div class="content position-relative">
|
||||||
|
<div v-html="content"></div>
|
||||||
|
</div>
|
||||||
<div class="bar" v-if="data.created_at > 0">
|
<div class="bar" v-if="data.created_at > 0">
|
||||||
<span class="bar-item"
|
<span class="bar-item"
|
||||||
><el-icon><Clock /></el-icon> {{ dateFormat(data.created_at) }}</span
|
><el-icon><Clock /></el-icon> {{ dateFormat(data.created_at) }}</span
|
||||||
@@ -71,7 +73,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<div class="content" v-html="content"></div>
|
<div class="content position-relative">
|
||||||
|
<div v-html="content"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bar" v-if="data.created_at > 0">
|
<div class="bar" v-if="data.created_at > 0">
|
||||||
<span class="bar-item"
|
<span class="bar-item"
|
||||||
@@ -88,7 +92,7 @@
|
|||||||
import { FormatFileSize, GetFileIcon, GetFileType } from '@/store/system'
|
import { FormatFileSize, GetFileIcon, GetFileType } from '@/store/system'
|
||||||
import { httpPost } from '@/utils/http'
|
import { httpPost } from '@/utils/http'
|
||||||
import { dateFormat, isImage, processPrompt } from '@/utils/libs'
|
import { dateFormat, isImage, processPrompt } from '@/utils/libs'
|
||||||
import { Clock } from '@element-plus/icons-vue'
|
import { Clock, Edit } from '@element-plus/icons-vue'
|
||||||
import hl from 'highlight.js'
|
import hl from 'highlight.js'
|
||||||
import MarkdownIt from 'markdown-it'
|
import MarkdownIt from 'markdown-it'
|
||||||
import emoji from 'markdown-it-emoji'
|
import emoji from 'markdown-it-emoji'
|
||||||
@@ -144,6 +148,9 @@ const finalTokens = ref(props.data.tokens)
|
|||||||
const content = ref(processPrompt(props.data.content))
|
const content = ref(processPrompt(props.data.content))
|
||||||
const files = ref([])
|
const files = ref([])
|
||||||
|
|
||||||
|
// 定义emit事件
|
||||||
|
const emit = defineEmits(['edit'])
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
processFiles()
|
processFiles()
|
||||||
})
|
})
|
||||||
@@ -475,4 +482,39 @@ const isExternalImg = (link, files) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.operations
|
||||||
|
display none
|
||||||
|
position absolute
|
||||||
|
right 5px
|
||||||
|
top 5px
|
||||||
|
|
||||||
|
.text-box
|
||||||
|
&:hover
|
||||||
|
.operations
|
||||||
|
display flex
|
||||||
|
gap 5px
|
||||||
|
|
||||||
|
.op-edit
|
||||||
|
cursor pointer
|
||||||
|
color #409eff
|
||||||
|
font-size 16px
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
color darken(#409eff, 10%)
|
||||||
|
|
||||||
|
.position-relative {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content:hover .action-buttons {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="!readOnly" class="flex">
|
<span v-if="!readOnly" class="flex">
|
||||||
<span class="bar-item" @click="reGenerate(data.prompt)">
|
<span class="bar-item" @click="reGenerate()">
|
||||||
<el-tooltip class="box-item" effect="dark" content="重新生成" placement="bottom">
|
<el-tooltip class="box-item" effect="dark" content="重新生成" placement="bottom">
|
||||||
<el-icon><Refresh /></el-icon>
|
<el-icon><Refresh /></el-icon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="!readOnly" class="flex">
|
<span v-if="!readOnly" class="flex">
|
||||||
<span class="bar-item bg" @click="reGenerate(data.prompt)">
|
<span class="bar-item bg" @click="reGenerate()">
|
||||||
<el-tooltip class="box-item" effect="dark" content="重新生成" placement="bottom">
|
<el-tooltip class="box-item" effect="dark" content="重新生成" placement="bottom">
|
||||||
<el-icon><Refresh /></el-icon>
|
<el-icon><Refresh /></el-icon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@@ -233,9 +233,8 @@ const stopSynthesis = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 重新生成
|
// 重新生成
|
||||||
const reGenerate = (prompt) => {
|
const reGenerate = () => {
|
||||||
console.log(prompt)
|
emits('regen')
|
||||||
emits('regen', prompt)
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -264,7 +264,7 @@
|
|||||||
<welcome @send="autofillPrompt" />
|
<welcome @send="autofillPrompt" />
|
||||||
</div>
|
</div>
|
||||||
<div v-for="item in chatData" :key="item.id" v-else>
|
<div v-for="item in chatData" :key="item.id" v-else>
|
||||||
<chat-prompt v-if="item.type === 'prompt'" :data="item" :list-style="listStyle" />
|
<chat-prompt v-if="item.type === 'prompt'" :data="item" :list-style="listStyle" @edit="editUserPrompt" />
|
||||||
<chat-reply
|
<chat-reply
|
||||||
v-else-if="item.type === 'reply'"
|
v-else-if="item.type === 'reply'"
|
||||||
:data="item"
|
:data="item"
|
||||||
@@ -1189,30 +1189,108 @@ const stopGenerate = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 重新生成
|
// 重新生成
|
||||||
const reGenerate = function (prompt) {
|
const reGenerate = function () {
|
||||||
disableInput(false)
|
// 恢复发送按钮状态
|
||||||
const text = '重新回答下述问题:' + prompt
|
canSend.value = true;
|
||||||
// 追加消息
|
showStopGenerate.value = false;
|
||||||
chatData.value.push({
|
|
||||||
type: 'prompt',
|
// 查找最后的用户消息和AI回复并删除
|
||||||
id: randString(32),
|
if (chatData.value.length >= 2) {
|
||||||
icon: loginUser.value.avatar,
|
// 从后往前找,如果最后一条是AI回复,再往前一条是用户消息
|
||||||
content: text,
|
if (chatData.value[chatData.value.length - 1].type === 'reply') {
|
||||||
})
|
// 删除AI回复
|
||||||
store.socket.conn.send(
|
chatData.value.pop();
|
||||||
JSON.stringify({
|
|
||||||
channel: 'chat',
|
// 如果此时最后一条是用户消息,也删除它
|
||||||
type: 'text',
|
if (chatData.value.length > 0 && chatData.value[chatData.value.length - 1].type === 'prompt') {
|
||||||
body: {
|
// 保存用户消息内容,填入输入框
|
||||||
role_id: roleId.value,
|
const userPrompt = chatData.value[chatData.value.length - 1].content;
|
||||||
model_id: modelID.value,
|
// 删除用户消息
|
||||||
chat_id: chatId.value,
|
chatData.value.pop();
|
||||||
content: text,
|
// 填入输入框
|
||||||
tools: toolSelected.value,
|
prompt.value = userPrompt;
|
||||||
stream: stream.value,
|
}
|
||||||
},
|
}
|
||||||
})
|
}
|
||||||
)
|
|
||||||
|
// 将光标定位到输入框并聚焦
|
||||||
|
nextTick(() => {
|
||||||
|
if (inputRef.value) {
|
||||||
|
inputRef.value.focus();
|
||||||
|
// 触发输入事件以更新文本高度
|
||||||
|
onInput({ keyCode: null });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑用户消息
|
||||||
|
const editUserPrompt = function (messageId) {
|
||||||
|
// 找到要编辑的消息及其索引
|
||||||
|
let messageIndex = -1;
|
||||||
|
let messageContent = '';
|
||||||
|
|
||||||
|
for (let i = 0; i < chatData.value.length; i++) {
|
||||||
|
if (chatData.value[i].id === messageId) {
|
||||||
|
messageIndex = i;
|
||||||
|
messageContent = chatData.value[i].content;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messageIndex === -1) return;
|
||||||
|
|
||||||
|
// 弹出编辑对话框
|
||||||
|
ElMessageBox.prompt('', '编辑消息', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
inputValue: messageContent,
|
||||||
|
inputType: 'textarea',
|
||||||
|
customClass: 'edit-prompt-dialog',
|
||||||
|
roundButton: true
|
||||||
|
}).then(({ value }) => {
|
||||||
|
if (value.trim() === '') {
|
||||||
|
ElMessage.warning('消息内容不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新用户消息
|
||||||
|
chatData.value[messageIndex].content = value;
|
||||||
|
|
||||||
|
// 移除该消息之后的所有消息
|
||||||
|
chatData.value = chatData.value.slice(0, messageIndex + 1);
|
||||||
|
|
||||||
|
// 添加空回复消息
|
||||||
|
const _role = getRoleById(roleId.value);
|
||||||
|
chatData.value.push({
|
||||||
|
chat_id: chatId,
|
||||||
|
role_id: roleId.value,
|
||||||
|
type: 'reply',
|
||||||
|
id: randString(32),
|
||||||
|
icon: _role['icon'],
|
||||||
|
content: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
disableInput(false);
|
||||||
|
|
||||||
|
// 发送编辑后的消息
|
||||||
|
store.socket.conn.send(
|
||||||
|
JSON.stringify({
|
||||||
|
channel: 'chat',
|
||||||
|
type: 'text',
|
||||||
|
body: {
|
||||||
|
role_id: roleId.value,
|
||||||
|
model_id: modelID.value,
|
||||||
|
chat_id: chatId.value,
|
||||||
|
content: value,
|
||||||
|
tools: toolSelected.value,
|
||||||
|
stream: stream.value,
|
||||||
|
edit_message: true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}).catch(() => {
|
||||||
|
// 取消编辑
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const chatName = ref('')
|
const chatName = ref('')
|
||||||
|
|||||||
Reference in New Issue
Block a user