feat: 创建项目ID

This commit is contained in:
2026-02-25 11:00:31 +08:00
parent 37cedb5272
commit 9fbeb408fc
9 changed files with 288 additions and 173 deletions

View File

@@ -8,8 +8,13 @@
<SvgIcon name="equal" color="#0d0d0d" size="24" />
</div>
<div class="agent-body flex-1 flex flex-col">
<List ref="listRef" :message-list="messageList" />
<Input is-agent-mode @send="handleSendMessage" />
<List ref="listRef" :message-list="messageList" @regenerate="handleRegenerate" />
<Input
is-agent-mode
:generating="isGenerating"
@send="handleSendMessage"
@pause="handlePause"
/>
</div>
</div>
</template>
@@ -20,7 +25,7 @@
import Input from '../../components/Input.vue'
import { fetchAgentReply } from '@/api/agent'
import type { AgentParamsType } from '@/api/agent'
import { useUserInfoStore,useProjectStore } from '@/stores'
import { useUserInfoStore, useProjectStore } from '@/stores'
import { useAgentStore } from '@/stores/agent'
const userStore = useUserInfoStore()
@@ -37,8 +42,10 @@
const messageList = ref([])
const listRef = ref()
const isGenerating = ref(false)
const isPaused = ref(false) // 标记是否为主动暂停
const params = reactive<AgentParamsType>({
projectID: '1',
projectID: projectStore.state.id,
message: '',
token: userStore.state.token,
versionID: '',
@@ -51,22 +58,32 @@
imageUrlList: []
})
const abort = new AbortController()
// 每次请求时创建新的 AbortController
let abort: AbortController
const createAbortController = () => {
// 如果已有未完成的中止,先中止它
if (abort) {
abort.abort()
}
abort = new AbortController()
return abort
}
onUnmounted(() => {
abort.abort()
abort?.abort()
})
onMounted(() => {
// 检查 store 中是否有初始项目数据
projectStore.setId('1') // 临时设置项目ID为1实际应用中应根据上下文动态设置
// projectStore.setId('1') // 临时设置项目ID为1实际应用中应根据上下文动态设置
const initialData = agentStore.getInitialProjectData
if (initialData) {
// 等待页面渲染完成后自动发送初始消息
params.configParams = {
type: initialData.type || 'Chair',
region: initialData.area || 'China',
style: initialData.style || 'Transitional',
type: initialData.type ,
region: initialData.area,
style: initialData.style ,
temperature: 0.7
}
handleSendMessage({
@@ -83,15 +100,21 @@
const handleSendMessage = async (message: {
text: string
images: Array<{ url: string; name: string }>
}) => {
}, skipUserMessage = false) => {
console.log('Message sent:', message)
isPaused.value = false
isGenerating.value = true
params.message = message.text
params.imageUrlList = message.images || []
messageList.value.push({
id: messageList.value.length + 1,
text: message.text,
isUser: true
})
// 如果不是重新生成模式,则添加用户消息到列表
if (!skipUserMessage) {
messageList.value.push({
id: messageList.value.length + 1,
text: message.text,
isUser: true
})
}
// Add AI loading message
const aiMessage = reactive({
@@ -106,6 +129,9 @@
})
messageList.value.push(aiMessage)
// 创建新的 AbortController
const abortController = createAbortController()
// console.log('token---', params.token, '参数---', params)
try {
@@ -116,7 +142,7 @@
const response = await fetch(`/api/ai-design/chat?${urlParams.toString()}`, {
method: 'GET',
signal: abort.signal
signal: abortController.signal
})
// 检查响应内容类型,判断是否为流式响应
@@ -128,9 +154,12 @@
// 非流式错误响应,使用 text() 读取错误信息
const errorText = await response.text()
console.error('请求错误:', errorText)
aiMessage.text = '发送失败,请重试'
if (!isPaused.value) {
aiMessage.text = '发送失败,请重试'
}
aiMessage.streaming = false
aiMessage.loading = false
isGenerating.value = false
return
}
@@ -143,9 +172,12 @@
} catch (e) {
console.error('非流式响应文本:', text)
}
aiMessage.text = '发送失败,请重试'
if (!isPaused.value) {
aiMessage.text = '发送失败,请重试'
}
aiMessage.streaming = false
aiMessage.loading = false
isGenerating.value = false
return
}
@@ -181,26 +213,26 @@
// 过滤掉 id: 等字段,只取 data:
let isNodeIdEvent = false
if(event.startsWith('event:')){
if (event.startsWith('event:')) {
isNodeIdEvent = true
// continue
}
const dataLines = event
.split(/\n/)
.filter((line) => line.startsWith('data:'))
.map((line) => line.replace(/^data:\s*/, '').trim())
console.log('dataLInes',dataLines);
if(isNodeIdEvent){
.split(/\n/)
.filter((line) => line.startsWith('data:'))
.map((line) => line.replace(/^data:\s*/, '').trim())
console.log('dataLInes', dataLines)
if (isNodeIdEvent) {
params.versionID = dataLines[0]
}
if (dataLines.length === 0) continue
const jsonText = dataLines.join('\n')
try {
const jsonData = JSON.parse(jsonText)
// 赋值 project_id 和 version_id
if (jsonData.project_id) params.projectID = jsonData.project_id
if (jsonData.version_id) params.versionID = jsonData.version_id
@@ -215,6 +247,7 @@
if (jsonData.type === 'end') {
aiMessage.streaming = false
aiMessage.loading = false
isGenerating.value = false
flag = false
break
}
@@ -224,6 +257,7 @@
console.log('结束-----------------------')
aiMessage.streaming = false
aiMessage.loading = false
isGenerating.value = false
flag = false
break
}
@@ -239,19 +273,59 @@
}
} catch (error) {
console.error('流式传输错误:', error)
aiMessage.text = '发送失败,请重试'
if (!isPaused.value) {
aiMessage.text = '发送失败,请重试'
}
aiMessage.streaming = false
aiMessage.loading = false
isGenerating.value = false
} finally {
reader.releaseLock()
}
} catch (error) {
console.error('fetch请求失败:', error)
aiMessage.text = '发送失败,请重试'
if (!isPaused.value) {
aiMessage.text = '发送失败,请重试'
}
aiMessage.streaming = false
aiMessage.loading = false
isGenerating.value = false
}
}
const handlePause = () => {
isPaused.value = true
isGenerating.value = false
abort?.abort()
}
const handleRegenerate = async (aiMessage: any) => {
// 找到当前 AI 消息在列表中的索引
const aiIndex = messageList.value.findIndex((msg) => msg.id === aiMessage.id)
if (aiIndex === -1) return
// 找到对应的用户消息AI 消息前面的最近一条用户消息)
let userMessage = null
for (let i = aiIndex - 1; i >= 0; i--) {
if (messageList.value[i].isUser) {
userMessage = messageList.value[i]
break
}
}
if (!userMessage) return
// 删除当前的 AI 回复消息
messageList.value.splice(aiIndex, 1)
// 重新调用 API跳过用户消息添加因为用户消息已存在
await handleSendMessage(
{
text: userMessage.text,
images: userMessage.images || []
},
true
)
}
</script>
<style lang="less" scoped>

View File

@@ -81,6 +81,8 @@
return str
})
const emit = defineEmits(['regenerate'])
const operateList = ref([
{
name: 'thumbUp',
@@ -97,7 +99,7 @@
{
name: 'refreshTransparent',
action: () => {
console.log('refresh')
emit('regenerate')
}
},
{

View File

@@ -1,6 +1,6 @@
<template>
<div class="agent-list flex flex-col flex-1" ref="listContainer">
<Item v-for="message in messageList" :key="message.id" :content="message" />
<Item v-for="message in messageList" :key="message.id" :content="message" @regenerate="$emit('regenerate', message)" />
</div>
</template>
@@ -12,6 +12,8 @@
messageList: Array<any>
}>()
const emit = defineEmits(['regenerate'])
const listContainer = ref<HTMLDivElement>()
const scrollToBottom = () => {