feat: 更新前端页面
- Agents, Chat, Settings, Skill, Tools - Account, Plan, Script - useSkills composable Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,76 @@ const chatSessions = ref<ChatSession[]>([
|
||||
{ id: 3, title: '数据分析咨询', agentId: 4, lastMessage: 'DeepSeek: 好的', timestamp: new Date(Date.now() - 86400000) },
|
||||
])
|
||||
|
||||
// 群聊数据
|
||||
interface GroupChat {
|
||||
id: number
|
||||
name: string
|
||||
members: string[]
|
||||
lastMessage: string
|
||||
timestamp: Date
|
||||
}
|
||||
|
||||
const groupChats = ref<GroupChat[]>([
|
||||
{ id: 1, name: 'AI 讨论组', members: ['Claude', 'GPT-4', 'Gemini'], lastMessage: '我们来讨论一下...', timestamp: new Date(Date.now() - 1800000) },
|
||||
{ id: 2, name: '编程助手', members: ['Claude', 'DeepSeek'], lastMessage: '这段代码有问题吗?', timestamp: new Date(Date.now() - 3600000) },
|
||||
{ id: 3, name: '创意头脑风暴', members: ['GPT-4', 'Claude', 'Kimi'], lastMessage: '有个新想法...', timestamp: new Date(Date.now() - 7200000) },
|
||||
])
|
||||
|
||||
// 智能体选择弹窗状态
|
||||
const showAgentSelector = ref(false)
|
||||
const selectMode = ref<'single' | 'group'>('single')
|
||||
const selectedAgents = ref<Agent[]>([])
|
||||
const groupChatName = ref('')
|
||||
|
||||
// 打开智能体选择器
|
||||
const openAgentSelector = (mode: 'single' | 'group') => {
|
||||
selectMode.value = mode
|
||||
selectedAgents.value = []
|
||||
groupChatName.value = ''
|
||||
showAgentSelector.value = true
|
||||
}
|
||||
|
||||
// 切换智能体选择(群聊模式)
|
||||
const toggleAgentSelection = (agent: Agent) => {
|
||||
const index = selectedAgents.value.findIndex(a => a.id === agent.id)
|
||||
if (index > -1) {
|
||||
selectedAgents.value.splice(index, 1)
|
||||
} else {
|
||||
selectedAgents.value.push(agent)
|
||||
}
|
||||
}
|
||||
|
||||
// 确认选择
|
||||
const confirmAgentSelection = () => {
|
||||
if (selectMode.value === 'single') {
|
||||
// 单聊模式:选择一个智能体开始对话
|
||||
if (selectedAgents.value.length > 0) {
|
||||
selectedAgent.value = selectedAgents.value[0]
|
||||
messages.value = [
|
||||
{ id: 1, role: 'assistant', content: `你好!我是 ${selectedAgent.value.name},你的 AI 助手。有什么我可以帮助你的吗?`, timestamp: new Date() }
|
||||
]
|
||||
}
|
||||
} else {
|
||||
// 群聊模式:选择多个智能体
|
||||
const name = groupChatName.value.trim() || `群聊 (${selectedAgents.value.length}人)`
|
||||
console.log('创建群聊:', { name, members: selectedAgents.value })
|
||||
// 添加到群聊列表
|
||||
groupChats.value.unshift({
|
||||
id: Date.now(),
|
||||
name: name,
|
||||
members: selectedAgents.value.map(a => a.name),
|
||||
lastMessage: 'New group created',
|
||||
timestamp: new Date()
|
||||
})
|
||||
}
|
||||
showAgentSelector.value = false
|
||||
}
|
||||
|
||||
// 取消选择
|
||||
const cancelAgentSelection = () => {
|
||||
showAgentSelector.value = false
|
||||
}
|
||||
|
||||
// 侧边栏展开/收起状态
|
||||
const sidebarCollapsed = ref(false)
|
||||
|
||||
@@ -398,15 +468,26 @@ const toggleSidebar = () => {
|
||||
|
||||
<!-- 新建对话按钮 -->
|
||||
<div class="p-3">
|
||||
<button
|
||||
@click="newChat"
|
||||
class="w-full flex items-center gap-2 px-3 py-2.5 bg-orange-500 hover:bg-orange-400 rounded-lg text-white text-sm font-medium transition-all duration-200"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
|
||||
</svg>
|
||||
<span>新建对话</span>
|
||||
</button>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
@click="openAgentSelector('single')"
|
||||
class="flex-1 flex items-center justify-center gap-2 px-3 py-2.5 bg-orange-500 hover:bg-orange-400 rounded-lg text-white text-sm font-medium transition-all duration-200"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
|
||||
</svg>
|
||||
<span>新建对话</span>
|
||||
</button>
|
||||
<button
|
||||
@click="openAgentSelector('group')"
|
||||
class="flex-1 flex items-center justify-center gap-2 px-3 py-2.5 bg-dark-700 hover:bg-dark-600 border border-dark-500 rounded-lg text-white/80 text-sm font-medium transition-all duration-200"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>
|
||||
</svg>
|
||||
<span>新建群聊</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI 助手选择 -->
|
||||
@@ -432,27 +513,115 @@ const toggleSidebar = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 历史对话列表 -->
|
||||
<!-- 群聊列表 -->
|
||||
<div class="flex-1 overflow-y-auto px-3 pb-3">
|
||||
<div class="text-xs text-white/40 uppercase tracking-wider mb-2 px-1">最近对话</div>
|
||||
<div class="text-xs text-white/40 uppercase tracking-wider mb-2 px-1">群聊</div>
|
||||
<div class="space-y-1">
|
||||
<button
|
||||
v-for="session in chatSessions"
|
||||
:key="session.id"
|
||||
@click="selectSession(session)"
|
||||
v-for="group in groupChats"
|
||||
:key="group.id"
|
||||
class="w-full text-left px-3 py-2.5 rounded-lg hover:bg-white/5 transition-all duration-200 group"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<svg class="w-4 h-4 text-white/30 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"></path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>
|
||||
</svg>
|
||||
<span class="text-sm text-white/70 group-hover:text-white truncate">{{ session.title }}</span>
|
||||
<span class="text-sm text-white/70 group-hover:text-white truncate">{{ group.name }}</span>
|
||||
</div>
|
||||
<div class="text-xs text-white/30 mt-1 pl-6">{{ formatRelativeTime(session.timestamp) }}</div>
|
||||
<div class="text-xs text-white/30 mt-1 pl-6">{{ group.members.length }} members</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 智能体选择弹窗 -->
|
||||
<Teleport to="body">
|
||||
<Transition name="fade">
|
||||
<div v-if="showAgentSelector" class="fixed inset-0 bg-black/60 flex items-center justify-center z-50" @click="cancelAgentSelection">
|
||||
<div class="bg-dark-800 rounded-xl w-full max-w-md border border-dark-600 shadow-2xl" @click.stop>
|
||||
<div class="p-4 border-b border-dark-600">
|
||||
<h3 class="text-lg font-semibold text-white">
|
||||
{{ selectMode === 'single' ? '选择智能体' : '选择群聊成员' }}
|
||||
</h3>
|
||||
<p class="text-sm text-gray-400 mt-1">
|
||||
{{ selectMode === 'single' ? '选择一个智能体开始对话' : '选择多个智能体创建群聊' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="p-4 max-h-80 overflow-y-auto">
|
||||
<!-- 群聊名称输入框 -->
|
||||
<div v-if="selectMode === 'group'" class="mb-4">
|
||||
<input
|
||||
v-model="groupChatName"
|
||||
type="text"
|
||||
placeholder="Enter group name..."
|
||||
class="w-full bg-dark-700 border border-dark-500 rounded-lg px-4 py-2.5 text-white placeholder-gray-500 focus:outline-none focus:border-primary-orange"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<button
|
||||
v-for="agent in chatAgents"
|
||||
:key="agent.id"
|
||||
@click="selectMode === 'group' ? toggleAgentSelection(agent) : (selectedAgents = [agent], confirmAgentSelection())"
|
||||
class="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg transition-all duration-200"
|
||||
:class="selectedAgents.some(a => a.id === agent.id)
|
||||
? 'bg-orange-500/20 border border-orange-500/50'
|
||||
: 'bg-dark-700 hover:bg-dark-600 border border-transparent'"
|
||||
>
|
||||
<span class="text-xl">{{ agent.avatar }}</span>
|
||||
<div class="flex-1 text-left">
|
||||
<div class="text-white font-medium">{{ agent.name }}</div>
|
||||
<div class="text-xs text-gray-400">{{ agent.description }}</div>
|
||||
</div>
|
||||
<span
|
||||
v-if="agent.status === 'online'"
|
||||
class="w-2 h-2 rounded-full bg-emerald-400"
|
||||
></span>
|
||||
<span
|
||||
v-if="selectMode === 'group' && selectedAgents.some(a => a.id === agent.id)"
|
||||
class="w-5 h-5 rounded-full bg-orange-500 flex items-center justify-center"
|
||||
>
|
||||
<svg class="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-4 border-t border-dark-600 flex gap-3">
|
||||
<button
|
||||
@click="cancelAgentSelection"
|
||||
class="flex-1 py-2.5 bg-dark-700 hover:bg-dark-600 text-gray-300 rounded-lg transition-colors"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
v-if="selectMode === 'group'"
|
||||
@click="confirmAgentSelection"
|
||||
:disabled="selectedAgents.length < 2"
|
||||
class="flex-1 py-2.5 bg-orange-500 hover:bg-orange-400 text-white rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
Create Group ({{ selectedAgents.length }})
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user