debug
This commit is contained in:
parent
f948dfc45f
commit
b07e3411e3
|
|
@ -1,8 +1,13 @@
|
|||
<script setup>
|
||||
import { useAuth } from './utils/useAuth.js'
|
||||
import AppHeader from './components/AppHeader.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const { isLoggedIn } = useAuth()
|
||||
const router = useRouter()
|
||||
|
||||
// 设置全局 router 引用,供 api.js 响应拦截器使用
|
||||
window.__VUE_ROUTER__ = router
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -157,12 +157,11 @@ const regenerateIcon = `<svg viewBox="0 0 24 24" width="14" height="14" fill="no
|
|||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 8px 0 0;
|
||||
margin-top: 8px;
|
||||
padding-top: 10px;
|
||||
font-size: 12px;
|
||||
color: var(--text-tertiary);
|
||||
border-top: 1px solid transparent;
|
||||
margin-top: 8px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -194,8 +194,9 @@ function handleBack() {
|
|||
<div v-if="sidebarTab === 'roomAgents' && room" class="sidebar-tab-content">
|
||||
<div class="sidebar-header sidebar-header-row">
|
||||
<button class="btn-back" @click="handleBack">
|
||||
<svg width="18" height="18">
|
||||
<use href="#arrow-left-icon"/>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="19" y1="12" x2="5" y2="12"></line>
|
||||
<polyline points="12 19 5 12 12 5"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
<span class="sidebar-title">{{ room.title }}</span>
|
||||
|
|
|
|||
|
|
@ -30,8 +30,13 @@ api.interceptors.response.use(
|
|||
if (error.response?.status === 401) {
|
||||
localStorage.removeItem('access_token')
|
||||
localStorage.removeItem('user')
|
||||
// 使用 Vue Router 跳转,避免 SPA 路由丢失
|
||||
if (window.__VUE_ROUTER__) {
|
||||
window.__VUE_ROUTER__.push('/auth')
|
||||
} else {
|
||||
window.location.href = '/auth'
|
||||
}
|
||||
}
|
||||
return Promise.reject(error.response?.data || error.message)
|
||||
}
|
||||
)
|
||||
|
|
@ -106,6 +111,7 @@ export const chatRoomsAPI = {
|
|||
delete: (id) => api.delete(`/chat-rooms/${id}`),
|
||||
getMessages: (id) => api.get(`/chat-rooms/${id}/messages`),
|
||||
start: (id) => `/api/chat-rooms/${id}/start`,
|
||||
// 注意: start 返回路径字符串,由调用方使用 fetch 处理 SSE 流
|
||||
stop: (id) => api.post(`/chat-rooms/${id}/stop`),
|
||||
reset: (id) => api.post(`/chat-rooms/${id}/reset`),
|
||||
addAgent: (roomId, data) => api.post(`/chat-rooms/${roomId}/agents`, data),
|
||||
|
|
|
|||
|
|
@ -108,24 +108,24 @@ class ParallelStreamManager {
|
|||
break
|
||||
|
||||
case 'message_start':
|
||||
store.startAgentStream(roomId, data.agent_id || data.agentId, data)
|
||||
store.startAgentStream(roomId, data.agent_id, data)
|
||||
break
|
||||
|
||||
case 'message_chunk':
|
||||
store.updateAgentContent(roomId, data.agent_id || data.agentId, {
|
||||
store.updateAgentContent(roomId, data.agent_id, {
|
||||
content: data.content || '',
|
||||
progress: data.progress || 0
|
||||
})
|
||||
break
|
||||
|
||||
case 'message_end':
|
||||
store.completeAgentStream(roomId, data.agent_id || data.agentId, data)
|
||||
store.completeAgentStream(roomId, data.agent_id, data)
|
||||
break
|
||||
|
||||
case 'agent_error':
|
||||
store.errorAgentStream(roomId, data.agent_id || data.agentId, {
|
||||
store.errorAgentStream(roomId, data.agent_id, {
|
||||
message: data.error,
|
||||
agentName: data.agent_name || data.agentName
|
||||
agentName: data.agent_name
|
||||
})
|
||||
break
|
||||
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ export function useConversations() {
|
|||
convMessages.value = res.data?.messages || []
|
||||
// 加载完成后强制滚动到底部(初始加载总是显示最新消息)
|
||||
nextTick(() => {
|
||||
if (typeof onInitialScroll === 'function') {
|
||||
onInitialScroll()
|
||||
if (typeof initialScrollCallback === 'function') {
|
||||
initialScrollCallback()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -278,10 +278,10 @@ export function useConversations() {
|
|||
}
|
||||
|
||||
// 初始滚动回调(由外部设置)
|
||||
let onInitialScroll = null
|
||||
let initialScrollCallback = null
|
||||
|
||||
const setOnInitialScroll = (callback) => {
|
||||
onInitialScroll = callback
|
||||
initialScrollCallback = callback
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -94,14 +94,15 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="chat-input-area">
|
||||
<input
|
||||
<div class="input-wrapper">
|
||||
<textarea
|
||||
v-model="newMessage"
|
||||
@keyup.enter="handleSend"
|
||||
type="text"
|
||||
placeholder="输入消息..."
|
||||
@keydown.enter.exact.prevent="handleSend"
|
||||
placeholder="输入消息... (Shift+Enter 换行)"
|
||||
class="chat-input"
|
||||
:disabled="sending"
|
||||
/>
|
||||
rows="3"
|
||||
></textarea>
|
||||
<button @click="handleSend" class="btn-send" :disabled="sending || !newMessage.trim()" title="发送">
|
||||
<svg v-if="!sending" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="22" y1="2" x2="11" y2="13"></line>
|
||||
|
|
@ -111,6 +112,7 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
|
|
@ -424,10 +426,51 @@ onUnmounted(() => {
|
|||
.loading-messages .spinner-small { margin-bottom: 0.5rem; }
|
||||
|
||||
/* 聊天输入区 */
|
||||
.chat-input-area { padding: 1rem; border-top: 1px solid var(--border-light); display: flex; gap: 0.75rem; }
|
||||
.chat-input { flex: 1; padding: 0.65rem 0.9rem; border: 1px solid var(--border-input); border-radius: 8px; background: var(--bg-input); color: var(--text-primary); font-size: 0.9rem; }
|
||||
.chat-input:focus { outline: none; border-color: var(--accent-primary); }
|
||||
.btn-send { width: 40px; height: 40px; background: var(--accent-primary); color: white; border: none; border-radius: 8px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease; }
|
||||
.chat-input-area { padding: 1rem; border-top: 1px solid var(--border-light); }
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
background: var(--bg-input);
|
||||
border: 1px solid var(--border-input);
|
||||
border-radius: 10px;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
.input-wrapper:focus-within { border-color: var(--accent-primary); }
|
||||
.chat-input {
|
||||
flex: 1;
|
||||
padding: 0.75rem 3rem 0.75rem 1rem;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.9rem;
|
||||
font-family: inherit;
|
||||
resize: none;
|
||||
min-height: 72px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.chat-input:focus { outline: none; }
|
||||
.chat-input:disabled { opacity: 0.6; }
|
||||
.btn-send {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
bottom: 8px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: var(--accent-primary);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
.btn-send:hover:not(:disabled) { background: var(--accent-primary-hover); transform: translateY(-1px); box-shadow: 0 2px 8px rgba(37, 99, 235, 0.3); }
|
||||
.btn-send:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue