feat: 创建项目ID
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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 = () => {
|
||||
|
||||
@@ -151,12 +151,16 @@
|
||||
<img src="@/assets/images/shining.png" class="shining-icon" alt="" />
|
||||
<span class="create-btn-text">{{ $t('Input.createProject') }}</span>
|
||||
</div>
|
||||
<img
|
||||
v-else
|
||||
src="@/assets/images/sender.png"
|
||||
class="sender-icon"
|
||||
@click="handleSendAgent"
|
||||
/>
|
||||
|
||||
<div v-else class="sender-btn flex flex-center" @click="handleSendAgent">
|
||||
<img
|
||||
v-show="!generating"
|
||||
src="@/assets/images/sender.png"
|
||||
alt=""
|
||||
class="sender-icon"
|
||||
/>
|
||||
<div v-show="generating" class="sender-pause" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!isAgentMode" class="report-btn flex flex-center" @click="toogltReportTag">
|
||||
@@ -171,24 +175,28 @@
|
||||
import { areaList } from '@/utils/area'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useAgentStore } from '@/stores/agent'
|
||||
import { useAgentStore, useProjectStore } from '@/stores'
|
||||
import lightIcon from '@/assets/images/light-icon.png'
|
||||
import closeIcon from '@/assets/images/close-icon.png'
|
||||
import { createProject } from '@/api/agent'
|
||||
// import Tag from './Tag.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const agentStore = useAgentStore()
|
||||
const projectStore = useProjectStore()
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
isAgentMode?: boolean
|
||||
generating?: boolean
|
||||
}>(),
|
||||
{
|
||||
isAgentMode: false
|
||||
isAgentMode: false,
|
||||
generating: false
|
||||
}
|
||||
)
|
||||
|
||||
const emits = defineEmits(['send'])
|
||||
const emits = defineEmits(['send', 'pause'])
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -424,7 +432,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
const handleSendAgent = () => {
|
||||
const handleSendAgent = async () => {
|
||||
if (props.generating) {
|
||||
emits('pause')
|
||||
return
|
||||
}
|
||||
if (!inputValue.value.trim()) return
|
||||
emits('send', { text: inputValue.value.trim(), images: uploadedImages.value })
|
||||
// 发送后清空输入框
|
||||
@@ -499,21 +511,22 @@
|
||||
}))
|
||||
)
|
||||
|
||||
const handleCreateProject = () => {
|
||||
const handleCreateProject = async () => {
|
||||
// 这里可以添加创建项目的逻辑
|
||||
const params = {
|
||||
type: typeValue.value,
|
||||
area: areaValue.value,
|
||||
style: styleValue.value
|
||||
style: styleValue.value,
|
||||
temperature: 0.7
|
||||
}
|
||||
|
||||
const projectres = await createProject(params)
|
||||
console.log('projectres', projectres)
|
||||
projectStore.setId(projectres)
|
||||
// 保存初始数据到 store
|
||||
agentStore.setInitialProjectData({
|
||||
text: inputValue.value.trim(),
|
||||
images: uploadedImages.value,
|
||||
type: typeValue.value,
|
||||
area: areaValue.value,
|
||||
style: styleValue.value
|
||||
...params
|
||||
})
|
||||
|
||||
console.log('Create project with:', params)
|
||||
@@ -736,10 +749,21 @@
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.sender-icon {
|
||||
.sender-btn {
|
||||
width: 3.2rem;
|
||||
height: 3.2rem;
|
||||
cursor: pointer;
|
||||
background-color: #ff7a51;
|
||||
border-radius: 50%;
|
||||
.sender-icon {
|
||||
width: 1.3rem;
|
||||
height: 1.3rem;
|
||||
}
|
||||
.sender-pause {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user