update
This commit is contained in:
parent
f5f8395ef9
commit
507925efde
@ -5,7 +5,7 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
image: icrypto-web:1.0.8
|
image: icrypto-web:1.0.9
|
||||||
container_name: icrypto-web
|
container_name: icrypto-web
|
||||||
ports:
|
ports:
|
||||||
- '6000:80'
|
- '6000:80'
|
||||||
|
|||||||
@ -1,7 +1,24 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, nextTick, computed, onMounted } from 'vue'
|
import { ref, nextTick, computed, onMounted, watch } from 'vue'
|
||||||
import { useUserStore } from '../stores/user'
|
import { useUserStore } from '../stores/user'
|
||||||
|
|
||||||
|
// 定义Agent类型
|
||||||
|
interface Agent {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
icon?: string
|
||||||
|
hello_prompt?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义API返回的Agent类型
|
||||||
|
interface AgentResponse {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
hello_prompt: string
|
||||||
|
}
|
||||||
|
|
||||||
// 获取用户状态
|
// 获取用户状态
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const isAuthenticated = computed(() => userStore.isAuthenticated)
|
const isAuthenticated = computed(() => userStore.isAuthenticated)
|
||||||
@ -11,17 +28,79 @@ const isVIP = computed(() => userInfo.value && userInfo.value.level >= 1)
|
|||||||
// 显示访问限制提示
|
// 显示访问限制提示
|
||||||
const showAccessDeniedAlert = ref(false)
|
const showAccessDeniedAlert = ref(false)
|
||||||
|
|
||||||
|
// Agent列表
|
||||||
|
const agents = ref<Agent[]>([])
|
||||||
|
const isLoadingAgents = ref(false)
|
||||||
|
|
||||||
|
// 当前选中的Agent
|
||||||
|
const selectedAgent = ref<Agent | null>(null)
|
||||||
|
|
||||||
// 根据环境选择API基础URL
|
// 根据环境选择API基础URL
|
||||||
const apiBaseUrl =
|
const apiBaseUrl =
|
||||||
import.meta.env.MODE === 'development' ? 'http://127.0.0.1:8000' : 'https://api.ibtc.work'
|
import.meta.env.MODE === 'development' ? 'http://127.0.0.1:8000' : 'https://api.ibtc.work'
|
||||||
|
|
||||||
|
// 获取Agent列表
|
||||||
|
const fetchAgents = async () => {
|
||||||
|
if (!isAuthenticated.value) return
|
||||||
|
|
||||||
|
isLoadingAgents.value = true
|
||||||
|
try {
|
||||||
|
const headers: Record<string, string> = {}
|
||||||
|
if (userStore.authHeader) {
|
||||||
|
headers['Authorization'] = userStore.authHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(`${apiBaseUrl}/agent/list`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
agents.value = data.map((agent: AgentResponse) => ({
|
||||||
|
...agent,
|
||||||
|
icon: '📊', // 可以根据agent类型设置不同的图标
|
||||||
|
}))
|
||||||
|
|
||||||
|
// 如果有Agent,默认选中第一个并显示问候语
|
||||||
|
if (agents.value.length > 0 && !selectedAgent.value) {
|
||||||
|
selectedAgent.value = agents.value[0]
|
||||||
|
addInitialGreeting(agents.value[0])
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取Agent列表失败:', error)
|
||||||
|
} finally {
|
||||||
|
isLoadingAgents.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当用户登录状态改变时获取Agent列表
|
||||||
|
onMounted(() => {
|
||||||
|
if (isAuthenticated.value) {
|
||||||
|
fetchAgents()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
interface ChatMessage {
|
||||||
|
role: 'user' | 'assistant' | 'thought'
|
||||||
|
content: string
|
||||||
|
files: Array<{
|
||||||
|
type: string
|
||||||
|
url: string
|
||||||
|
}>
|
||||||
|
thought?: {
|
||||||
|
thought: string
|
||||||
|
observation: string
|
||||||
|
tool: string
|
||||||
|
tool_input: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const userInput = ref('')
|
const userInput = ref('')
|
||||||
const chatHistory = ref([
|
const chatHistory = ref<ChatMessage[]>([])
|
||||||
{
|
|
||||||
role: 'assistant',
|
|
||||||
content: '你好!我是AI Agent,可以回答你的任何关于Web3的问题。请告诉我你想了解什么?',
|
|
||||||
},
|
|
||||||
])
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const messagesContainer = ref<HTMLElement | null>(null)
|
const messagesContainer = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
@ -48,13 +127,41 @@ const scrollToBottom = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加初始问候语
|
||||||
|
const addInitialGreeting = (agent: Agent) => {
|
||||||
|
chatHistory.value = [
|
||||||
|
{
|
||||||
|
role: 'assistant',
|
||||||
|
content:
|
||||||
|
agent.hello_prompt ||
|
||||||
|
'你好!我是AI Agent,可以回答你的任何关于Web3的问题。请告诉我你想了解什么?',
|
||||||
|
files: [],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听选中的Agent变化
|
||||||
|
watch(selectedAgent, (newAgent) => {
|
||||||
|
if (newAgent) {
|
||||||
|
addInitialGreeting(newAgent)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const sendMessage = async () => {
|
const sendMessage = async () => {
|
||||||
if (!userInput.value.trim() || isLoading.value || !isAuthenticated.value || !isVIP.value) return
|
if (
|
||||||
|
!userInput.value.trim() ||
|
||||||
|
isLoading.value ||
|
||||||
|
!isAuthenticated.value ||
|
||||||
|
!isVIP.value ||
|
||||||
|
!selectedAgent.value
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
// 添加用户消息到历史记录
|
// 添加用户消息到历史记录
|
||||||
chatHistory.value.push({
|
chatHistory.value.push({
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: userInput.value,
|
content: userInput.value,
|
||||||
|
files: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
// 滚动到底部以显示用户消息
|
// 滚动到底部以显示用户消息
|
||||||
@ -65,9 +172,11 @@ const sendMessage = async () => {
|
|||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
|
|
||||||
// 添加临时助手消息用于流式显示
|
// 添加临时助手消息用于流式显示
|
||||||
|
const tempMessageIndex = chatHistory.value.length
|
||||||
chatHistory.value.push({
|
chatHistory.value.push({
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
content: '',
|
content: 'AI 正在思考...',
|
||||||
|
files: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
await scrollToBottom()
|
await scrollToBottom()
|
||||||
@ -89,6 +198,7 @@ const sendMessage = async () => {
|
|||||||
headers,
|
headers,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
user_prompt: currentInput,
|
user_prompt: currentInput,
|
||||||
|
agent_id: selectedAgent.value.id,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -110,20 +220,57 @@ const sendMessage = async () => {
|
|||||||
if (done) break
|
if (done) break
|
||||||
|
|
||||||
const chunk = decoder.decode(value, { stream: true })
|
const chunk = decoder.decode(value, { stream: true })
|
||||||
responseText += chunk
|
const lines = chunk.split('\n')
|
||||||
|
|
||||||
// 更新最后一条消息(助手的回复)
|
for (const line of lines) {
|
||||||
const lastIndex = chatHistory.value.length - 1
|
if (!line.trim() || !line.startsWith('data: ')) continue
|
||||||
chatHistory.value[lastIndex].content = responseText
|
|
||||||
|
|
||||||
// 滚动到底部以跟随新内容
|
try {
|
||||||
await scrollToBottom()
|
const data = JSON.parse(line.slice(6))
|
||||||
|
|
||||||
|
switch (data.event) {
|
||||||
|
case 'agent_thought':
|
||||||
|
// 忽略思考过程
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'agent_message':
|
||||||
|
if (data.answer) {
|
||||||
|
responseText += data.answer
|
||||||
|
// 更新临时助手消息的内容
|
||||||
|
chatHistory.value[tempMessageIndex].content = responseText
|
||||||
|
await scrollToBottom()
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'message_file':
|
||||||
|
if (data.type === 'image') {
|
||||||
|
// 找到最后一条助手消息来添加文件
|
||||||
|
const lastIndex = chatHistory.value.length - 1
|
||||||
|
if (chatHistory.value[lastIndex].role === 'assistant') {
|
||||||
|
chatHistory.value[lastIndex].files.push({
|
||||||
|
type: 'image',
|
||||||
|
url: data.url,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'message_end':
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'tts_message':
|
||||||
|
// 处理语音合成消息
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析响应数据出错:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('调用API出错:', error)
|
console.error('调用API出错:', error)
|
||||||
// 更新最后一条消息显示错误
|
// 更新错误消息
|
||||||
const lastIndex = chatHistory.value.length - 1
|
chatHistory.value[tempMessageIndex].content = '抱歉,请求出错了。请稍后再试。'
|
||||||
chatHistory.value[lastIndex].content = '抱歉,请求出错了。请稍后再试。'
|
|
||||||
await scrollToBottom()
|
await scrollToBottom()
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
@ -176,46 +323,106 @@ const sendMessage = async () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 已登录且是VIP用户显示聊天界面 -->
|
<!-- 已登录且是VIP用户显示聊天界面 -->
|
||||||
<div v-else class="chat-container">
|
<div v-else class="main-container">
|
||||||
<div class="chat-header">
|
<!-- 左侧Agent选择列表 -->
|
||||||
<h2>Web3 AI Agent</h2>
|
<div class="agent-sidebar">
|
||||||
</div>
|
<div class="agent-list">
|
||||||
|
<div v-if="isLoadingAgents" class="agent-loading">加载中...</div>
|
||||||
<div ref="messagesContainer" class="chat-messages">
|
<template v-else>
|
||||||
<div
|
<div
|
||||||
v-for="(message, index) in chatHistory"
|
v-for="agent in agents"
|
||||||
:key="index"
|
:key="agent.id"
|
||||||
class="message"
|
class="agent-item"
|
||||||
:class="{
|
:class="{ 'agent-item-active': selectedAgent?.id === agent.id }"
|
||||||
'user-message': message.role === 'user',
|
@click="selectedAgent = agent"
|
||||||
'ai-message': message.role === 'assistant',
|
>
|
||||||
}"
|
<div class="agent-icon">{{ agent.icon }}</div>
|
||||||
>
|
<div class="agent-info">
|
||||||
<div class="message-content">
|
<div class="agent-name">{{ agent.name }}</div>
|
||||||
<p v-for="(line, i) in message.content.split('\n')" :key="i">
|
<div class="agent-description">{{ agent.description }}</div>
|
||||||
{{
|
</div>
|
||||||
line ||
|
</div>
|
||||||
(message.role === 'assistant' && isLoading && index === chatHistory.length - 1
|
</template>
|
||||||
? '...'
|
|
||||||
: line)
|
|
||||||
}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chat-input">
|
<!-- 右侧聊天界面 -->
|
||||||
<input
|
<div class="chat-container">
|
||||||
type="text"
|
<div class="chat-header">
|
||||||
v-model="userInput"
|
<div class="current-agent" v-if="selectedAgent">
|
||||||
@keyup.enter="sendMessage"
|
<span class="agent-icon">{{ selectedAgent.icon }}</span>
|
||||||
placeholder="输入您的问题..."
|
<span class="agent-name">{{ selectedAgent.name }}</span>
|
||||||
class="input-field"
|
</div>
|
||||||
:disabled="isLoading"
|
</div>
|
||||||
/>
|
|
||||||
<button class="send-button" @click="sendMessage" :disabled="isLoading">
|
<div ref="messagesContainer" class="chat-messages">
|
||||||
{{ isLoading ? '加载中...' : '发送' }}
|
<div
|
||||||
</button>
|
v-for="(message, index) in chatHistory"
|
||||||
|
:key="index"
|
||||||
|
class="message"
|
||||||
|
:class="{
|
||||||
|
'user-message': message.role === 'user',
|
||||||
|
'ai-message': message.role === 'assistant',
|
||||||
|
'thought-message': message.role === 'thought',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="message-content">
|
||||||
|
<template v-if="message.role === 'thought'">
|
||||||
|
<div class="thought-content">
|
||||||
|
<div v-if="message.thought?.thought" class="thought-item">
|
||||||
|
<span class="thought-label">思考:</span>
|
||||||
|
<span class="thought-text">{{ message.thought.thought }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="message.thought?.observation" class="thought-item">
|
||||||
|
<span class="thought-label">观察:</span>
|
||||||
|
<span class="thought-text">{{ message.thought.observation }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="message.thought?.tool" class="thought-item">
|
||||||
|
<span class="thought-label">工具:</span>
|
||||||
|
<span class="thought-text">{{ message.thought.tool }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="message.thought?.tool_input" class="thought-item">
|
||||||
|
<span class="thought-label">输入:</span>
|
||||||
|
<span class="thought-text">{{ message.thought.tool_input }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<p v-for="(line, i) in message.content.split('\n')" :key="i">
|
||||||
|
{{
|
||||||
|
line ||
|
||||||
|
(message.role === 'assistant' && isLoading && index === chatHistory.length - 1
|
||||||
|
? '...'
|
||||||
|
: line)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<!-- 显示图片文件 -->
|
||||||
|
<div v-if="message.files && message.files.length > 0" class="message-files">
|
||||||
|
<template
|
||||||
|
v-for="(file, fileIndex) in message.files.filter((f) => f.type === 'image')"
|
||||||
|
:key="fileIndex"
|
||||||
|
>
|
||||||
|
<img :src="file.url" :alt="'AI生成的图片'" class="message-image" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-input">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="userInput"
|
||||||
|
@keyup.enter="sendMessage"
|
||||||
|
:placeholder="`向${selectedAgent?.name}提问...`"
|
||||||
|
class="input-field"
|
||||||
|
:disabled="isLoading"
|
||||||
|
/>
|
||||||
|
<button class="send-button" @click="sendMessage" :disabled="isLoading">
|
||||||
|
{{ isLoading ? '加载中...' : '发送' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -412,26 +619,104 @@ const sendMessage = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 聊天界面样式 */
|
/* 聊天界面样式 */
|
||||||
.chat-container {
|
.main-container {
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
width: 100%;
|
||||||
|
height: calc(80vh - 150px);
|
||||||
|
min-height: 500px;
|
||||||
background-color: var(--color-bg-card);
|
background-color: var(--color-bg-card);
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
height: calc(80vh - 150px);
|
}
|
||||||
min-height: 500px;
|
|
||||||
|
.agent-sidebar {
|
||||||
|
width: 280px;
|
||||||
|
border-right: 1px solid var(--color-border);
|
||||||
|
background-color: var(--color-bg-elevated);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-list {
|
||||||
|
padding: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
background-color: var(--color-bg-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-item:hover {
|
||||||
|
border-color: var(--color-border-hover);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-item-active {
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
background-color: var(--color-bg-elevated);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-icon {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-info {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-name {
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-description {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-header {
|
.chat-header {
|
||||||
padding: 1rem 1.5rem;
|
padding: 1rem 1.5rem;
|
||||||
border-bottom: 1px solid var(--color-border);
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-header h2 {
|
.current-agent {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-agent .agent-icon {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
font-weight: 600;
|
}
|
||||||
|
|
||||||
|
.current-agent .agent-name {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-messages {
|
.chat-messages {
|
||||||
@ -441,7 +726,6 @@ const sendMessage = async () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 自定义滚动条样式 - 深色系 */
|
/* 自定义滚动条样式 - 深色系 */
|
||||||
@ -534,28 +818,78 @@ const sendMessage = async () => {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-files {
|
||||||
|
margin-top: 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-image {
|
||||||
|
max-width: 100%;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thought-message {
|
||||||
|
align-self: flex-start;
|
||||||
|
background-color: var(--color-bg-elevated);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thought-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thought-item {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thought-label {
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
min-width: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thought-text {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-loading {
|
||||||
|
padding: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.chat-container {
|
.main-container {
|
||||||
|
flex-direction: column;
|
||||||
height: 70vh;
|
height: 70vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-prompt {
|
.agent-sidebar {
|
||||||
height: 70vh;
|
width: 100%;
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vip-prompt {
|
.agent-list {
|
||||||
height: 70vh;
|
padding: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-item {
|
||||||
|
padding: 0.75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.login-prompt-actions {
|
.agent-item {
|
||||||
flex-direction: column;
|
width: 160px;
|
||||||
}
|
|
||||||
|
|
||||||
.vip-level-info {
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user