chore: 删除无效文件

This commit is contained in:
2026-02-11 16:50:46 +08:00
parent 115601be5f
commit 6221acfa30

View File

@@ -1,317 +0,0 @@
<template>
<div class="asistant-container flex flex-column">
<div class="header">
<HeaderTitle hasSetting styleType="3" @clickProfile="handleClickProfile" />
</div>
<div class="content flex-1">
<NoticeList
ref="noticeListRef"
:list="messageList"
:is-streaming="isStreaming"
:streaming-message="currentStreamingMessage"
/>
</div>
<div class="footer">
<InputArea @send-message="handleSendMessage" />
<div class="continue flex">
<div class="btn flex flex-center" @click="handleContinue">Generate</div>
</div>
</div>
<Profile ref="profileRef" />
</div>
</template>
<script setup lang="ts">
import HeaderTitle from '@/components/HeaderTitle.vue'
import NoticeList from './components/NoticeList.vue'
import InputArea from './components/InputArea.vue'
import Profile from '../Workshop/profile.vue'
import { ref, onMounted, onUnmounted, onActivated } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useUserInfoStore, useGenerateStore } from '@/stores'
import { streamChatAddress } from '@/api/workshop'
import { generateUUID } from '@/utils/tools'
import { showToast } from 'vant'
const router = useRouter()
const route = useRoute()
const generateStore = useGenerateStore()
const userInfoStore = useUserInfoStore()
defineOptions({
name: 'asistant'
})
// 定义NoticeList组件引用类型
interface NoticeListRef {
simulateSendMessage: () => void
scrollToBottom: () => void
}
// 定义消息类型
interface ChatMessage {
sessionId: string | number
type: string
content: string
timestamp: string
id?: string
self?: boolean
}
const profileRef = ref<InstanceType<typeof Profile> | null>(null)
const handleClickProfile = () => {
profileRef.value.open()
}
const noticeListRef = ref<NoticeListRef | null>(null)
const messageList = ref<ChatMessage[]>([])
// 流式消息相关状态
const isStreaming = ref<boolean>(false)
const currentStreamingMessage = ref<ChatMessage | null>(null)
const sessionId = ref<string>('')
const sendPrefilledMessage = () => {
const { message, ...restQuery } = route.query
if (typeof message === 'string' && message.trim()) {
handleSendMessage(message)
router.replace({
path: route.path,
query: restQuery
})
}
}
onMounted(() => {
console.log('1111111111111');
sessionId.value = Math.floor(Date.now() / 1000).toString()
generateStore.setSessionId(sessionId.value)
})
onActivated(() => {
sendPrefilledMessage()
noticeListRef.value?.scrollToBottom()
})
onUnmounted(() => {
abort.abort()
})
const handleSendMessage = (message: string): void => {
console.log('发送:', message)
// 添加用户消息到列表
const userMessage: ChatMessage = {
id: generateUUID(),
type: 'text',
content: message,
timestamp: new Date().toISOString(),
sessionId: sessionId.value,
self: true
}
messageList.value.push(userMessage)
// 开始流式接收AI回复
handleFetchMessage(message)
}
const abort = new AbortController()
const handleFetchMessage = (message: string) => {
const params = {
message: message,
sessionId: sessionId.value,
gender: userInfoStore.state.generateParams.sex
}
// 创建AI消息对象
const aiMessage: ChatMessage = {
id: generateUUID(),
type: 'text',
content: '',
timestamp: new Date().toISOString(),
sessionId: sessionId.value
}
// 添加到消息列表
isStreaming.value = true
messageList.value.push(aiMessage)
currentStreamingMessage.value = aiMessage
// 直接使用 fetch 进行流式请求
const token = userInfoStore.state.token
const baseURL = import.meta.env.MODE === 'development' ? '' : import.meta.env.VITE_APP_URL
// 构建查询参数
const queryParams = new URLSearchParams()
Object.entries(params).forEach(([key, value]) => {
queryParams.append(key, String(value))
})
const url = `${baseURL}${streamChatAddress}?${queryParams.toString()}`
fetch(url, {
method: 'GET',
headers: {
Authorization: token,
'Content-Type': 'application/json'
},
credentials: 'include'
})
.then(async (response) => {
// 检查响应内容类型,判断是否为流式响应
const contentType = response.headers.get('content-type') || ''
const isStreamResponse =
contentType.includes('text/event-stream') || contentType.includes('stream')
if (!response.ok) {
// 非流式错误响应,使用 text() 读取错误信息
const errorText = await response.text()
console.error('请求错误:', errorText)
showToast({
message: `failed to fetch: ${response.status}`,
position: 'top',
icon: 'none'
})
throw new Error(`发起对话错误--- ${response.status}: ${errorText}`)
}
// 不是流式响应,使用 text()读取错误信息
if (!isStreamResponse) {
const text = await response.text()
try {
const errorData = JSON.parse(text)
if (errorData.message || errorData.error) {
showToast({
message: errorData.message || errorData.error || '请求失败',
position: 'top',
icon: 'none'
})
}
} catch (e) {
// 如果不是 JSON直接显示文本内容
showToast({
message: text || '请求失败',
position: 'top',
icon: 'none'
})
throw new Error(text || '请求失败')
}
isStreaming.value = false
currentStreamingMessage.value = null
return
}
// 流式响应处理
let contentBody = ''
let buffer = ''
const reader = response.body?.getReader()
if (!reader) throw new Error('无法获取流读取器')
const decoder = new TextDecoder()
try {
let flag = true
while (flag) {
const { done, value } = await reader.read()
if (done) {
console.log('传输结束 end---', contentBody)
isStreaming.value = false
currentStreamingMessage.value = null
flag = false
break
}
buffer += decoder.decode(value, { stream: true })
// 优先按空行拆分事件块SSE标准
let events = buffer.split(/\n\n/)
buffer = events.pop() // 保留不完整块
for (let event of events) {
if (!event.trim()) continue
// 过滤掉 id: 等字段,只取 data:
const dataLines = event
.split(/\n/)
.filter((line) => line.startsWith('data:'))
.map((line) => line.replace(/^data:\s*/, '').trim())
if (dataLines.length === 0) continue
const jsonText = dataLines.join('\n')
try {
const jsonData = JSON.parse(jsonText)
if (jsonData.content && jsonData.content.length > 0 && jsonData.type !== 'end') {
contentBody += jsonData.content
currentStreamingMessage.value.content = contentBody
}
} catch (e) {
// JSON 不完整:保留到下一次循环
if (!jsonText.trim().endsWith('}')) {
buffer = 'data: ' + jsonText // 重新放回缓存
continue
} else {
console.warn('⚠️ JSON 格式错误,跳过:', jsonText)
}
}
}
}
} catch (error) {
console.error('流式传输错误:', error)
isStreaming.value = false
currentStreamingMessage.value = null
} finally {
reader.releaseLock()
}
})
.catch((error) => {
console.error('fetch请求失败:', error)
isStreaming.value = false
currentStreamingMessage.value = null
})
}
const handleContinue = () => {
// router.push('/workshop/selectStyle')
// 模拟接口之后再跳转
generateStore.clearProductData()
router.push('/workshop/selectStyle')
}
</script>
<style lang="less" scoped>
.asistant-container {
height: 100%;
overflow: hidden;
}
.header {
flex-shrink: 0;
}
.content {
overflow: hidden;
display: flex;
flex-direction: column;
}
.footer {
flex-shrink: 0;
.continue {
font-family: 'satoshiRegular';
font-size: 3.6rem;
color: #fff;
text-align: right;
padding: 2.6rem 4.5rem;
flex-direction: row-reverse;
.btn {
border-radius: 0.7rem;
background-color: #000;
width: 24.6rem;
height: 6.7rem;
box-sizing: border-box;
}
}
}
</style>