|
|
@@ -0,0 +1,609 @@
|
|
|
+<template>
|
|
|
+ <div class="sub-agent-panel">
|
|
|
+ <div class="sub-agent-panel-header">
|
|
|
+ <div class="sub-agent-panel-header-left">
|
|
|
+ <span class="sub-agent-panel-title">子智能体</span>
|
|
|
+ <span class="sub-agent-panel-desc">管理模型子智能体,启用后可在聊天里使用</span>
|
|
|
+ </div>
|
|
|
+ <div class="sub-agent-panel-close" @click="emit('close')">
|
|
|
+ <div class="close-icon"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="sub-agent-filter-bar">
|
|
|
+ <a-input v-model:value="searchKeyword" placeholder="搜索子智能体..." allow-clear size="small" class="sub-agent-search-input" />
|
|
|
+ <a-select v-model:value="filterStatus" size="small" class="sub-agent-filter-select">
|
|
|
+ <a-select-option value="all">全部</a-select-option>
|
|
|
+ <a-select-option value="enabled">已启用</a-select-option>
|
|
|
+ <a-select-option value="disabled">未启用</a-select-option>
|
|
|
+ </a-select>
|
|
|
+ </div>
|
|
|
+ <div class="sub-agent-summary">
|
|
|
+ <span class="sub-agent-summary-label">子智能体</span>
|
|
|
+ <span class="sub-agent-summary-count">{{ filteredAgents.length }}项</span>
|
|
|
+ <a-button type="primary" class="sub-agent-create-btn" @click="handleCreate">
|
|
|
+ <template #icon><PlusOutlined /></template>
|
|
|
+ 创建
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <div class="sub-agent-list" v-if="!loading">
|
|
|
+ <div v-for="agent in filteredAgents" :key="agent.name" class="sub-agent-item">
|
|
|
+ <div class="sub-agent-header">
|
|
|
+ <div class="sub-agent-name-wrapper">
|
|
|
+ <div class="sub-agent-item-icon"></div>
|
|
|
+ <span class="sub-agent-name">{{ agent.name }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="sub-agent-actions">
|
|
|
+ <a-switch :checked="agent.enabled" size="small" class="sub-agent-switch" @change="handleToggle(agent)" />
|
|
|
+ <div class="action-btn edit-btn" @click.stop="handleEdit(agent)" title="编辑"></div>
|
|
|
+ <div class="action-btn delete-btn" @click.stop="handleDelete(agent)" title="删除"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="sub-agent-desc">{{ agent.description }}</div>
|
|
|
+ <div class="sub-agent-detail-toggle" @click.stop="toggleExpand(agent.name)">
|
|
|
+ <span>{{ expandedNames.has(agent.name) ? '收起详情' : '查看详情' }}</span>
|
|
|
+ <div :class="['toggle-arrow', { expanded: expandedNames.has(agent.name) }]"></div>
|
|
|
+ </div>
|
|
|
+ <div v-if="expandedNames.has(agent.name)" class="sub-agent-detail">
|
|
|
+ <div v-if="agent.system_prompt" class="detail-section">
|
|
|
+ <div class="detail-label">系统提示词</div>
|
|
|
+ <div class="detail-prompt">{{ agent.system_prompt }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="detail-section">
|
|
|
+ <div class="detail-label">工具</div>
|
|
|
+ <div class="detail-tools" v-if="agent.tool_infos && agent.tool_infos.length > 0">
|
|
|
+ <span v-for="tool in agent.tool_infos" :key="tool.name" :class="['tool-tag', { missing: !tool.exists }]">
|
|
|
+ {{ tool.display_name || tool.name }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class="detail-tools-empty" v-else>继承主 Agent 全部工具</div>
|
|
|
+ </div>
|
|
|
+ <div class="detail-section" v-if="agent.model">
|
|
|
+ <div class="detail-label">模型</div>
|
|
|
+ <div class="detail-model">{{ agent.model }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="detail-section" v-if="agent.created_at">
|
|
|
+ <div class="detail-label">创建时间</div>
|
|
|
+ <div class="detail-time">{{ agent.created_at }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <a-empty v-if="filteredAgents.length === 0" description="暂无子智能体" />
|
|
|
+ </div>
|
|
|
+ <div class="sub-agent-loading" v-else>
|
|
|
+ <a-spin />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <CreateSubAgentModal
|
|
|
+ :visible="showCreateModal"
|
|
|
+ :editData="editData"
|
|
|
+ @close="showCreateModal = false"
|
|
|
+ @created="handleCreatedOrUpdated"
|
|
|
+ @updated="handleCreatedOrUpdated"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+ import { ref, computed } from 'vue';
|
|
|
+ import { PlusOutlined } from '@ant-design/icons-vue';
|
|
|
+ import { getSubAgents, deleteSubAgent, toggleSubAgent } from '../../api';
|
|
|
+ import { message, Modal } from 'ant-design-vue';
|
|
|
+ import CreateSubAgentModal from './CreateSubAgentModal.vue';
|
|
|
+
|
|
|
+ interface ToolInfo {
|
|
|
+ name: string;
|
|
|
+ display_name: string;
|
|
|
+ exists: boolean;
|
|
|
+ }
|
|
|
+
|
|
|
+ interface SubAgent {
|
|
|
+ name: string;
|
|
|
+ description: string;
|
|
|
+ system_prompt: string;
|
|
|
+ tools: string[];
|
|
|
+ tool_infos: ToolInfo[];
|
|
|
+ model: string;
|
|
|
+ enabled: boolean;
|
|
|
+ created_at: string;
|
|
|
+ updated_at: string;
|
|
|
+ }
|
|
|
+
|
|
|
+ const emit = defineEmits<{ (e: 'close'): void }>();
|
|
|
+
|
|
|
+ const agents = ref<SubAgent[]>([]);
|
|
|
+ const loading = ref(false);
|
|
|
+ const searchKeyword = ref('');
|
|
|
+ const filterStatus = ref<'all' | 'enabled' | 'disabled'>('all');
|
|
|
+ const showCreateModal = ref(false);
|
|
|
+ const editData = ref<SubAgent | null>(null);
|
|
|
+ const expandedNames = ref(new Set<string>());
|
|
|
+
|
|
|
+ const filteredAgents = computed(() => {
|
|
|
+ return agents.value.filter((agent) => {
|
|
|
+ const keyword = searchKeyword.value.trim().toLowerCase();
|
|
|
+ const matchKeyword = !keyword || agent.name.toLowerCase().includes(keyword) || agent.description.toLowerCase().includes(keyword);
|
|
|
+ const matchStatus = filterStatus.value === 'all' || (filterStatus.value === 'enabled' ? agent.enabled : !agent.enabled);
|
|
|
+ return matchKeyword && matchStatus;
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ const fetchSubAgents = async () => {
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const res = await getSubAgents();
|
|
|
+ agents.value = res?.subagents || res?.data || [];
|
|
|
+ } catch {
|
|
|
+ agents.value = [];
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const toggleExpand = (name: string) => {
|
|
|
+ if (expandedNames.value.has(name)) {
|
|
|
+ expandedNames.value.delete(name);
|
|
|
+ } else {
|
|
|
+ expandedNames.value.add(name);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleCreate = () => {
|
|
|
+ editData.value = null;
|
|
|
+ showCreateModal.value = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleEdit = (agent: SubAgent) => {
|
|
|
+ editData.value = agent;
|
|
|
+ showCreateModal.value = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleCreatedOrUpdated = async () => {
|
|
|
+ await fetchSubAgents();
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleToggle = async (agent: SubAgent) => {
|
|
|
+ try {
|
|
|
+ await toggleSubAgent(agent.name);
|
|
|
+ agent.enabled = !agent.enabled;
|
|
|
+ message.success(`子智能体「${agent.name}」已${agent.enabled ? '启用' : '禁用'}`);
|
|
|
+ } catch {
|
|
|
+ message.error('操作失败,请重试');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleDelete = (agent: SubAgent) => {
|
|
|
+ Modal.confirm({
|
|
|
+ title: '提示',
|
|
|
+ content: `是否删除子智能体「${agent.name}」?`,
|
|
|
+ okText: '确认',
|
|
|
+ cancelText: '取消',
|
|
|
+ wrapClassName: 'delete-task-confirm-modal',
|
|
|
+ onOk: async () => {
|
|
|
+ try {
|
|
|
+ await deleteSubAgent(agent.name);
|
|
|
+ message.success(`子智能体「${agent.name}」已删除`);
|
|
|
+ expandedNames.value.delete(agent.name);
|
|
|
+ await fetchSubAgents();
|
|
|
+ } catch {
|
|
|
+ message.error('删除失败,请重试');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ fetchSubAgents();
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="less">
|
|
|
+ .sub-agent-panel {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ overflow: hidden;
|
|
|
+ background-image: var(--img-chat-panel-bg);
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-panel-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 14px 20px;
|
|
|
+ border-bottom: 1px solid rgba(63, 80, 106, 0.25);
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ .sub-agent-panel-header-left {
|
|
|
+ display: flex;
|
|
|
+ align-items: baseline;
|
|
|
+ gap: 10px;
|
|
|
+ min-width: 0;
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-panel-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #e8edf3;
|
|
|
+ letter-spacing: 1px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-panel-desc {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #6a7a8a;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-panel-close {
|
|
|
+ width: 28px;
|
|
|
+ height: 28px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ cursor: pointer;
|
|
|
+ border-radius: 4px;
|
|
|
+ transition: background 0.2s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: rgba(255, 77, 79, 0.15);
|
|
|
+ }
|
|
|
+
|
|
|
+ .close-icon {
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ background-image: var(--img-chat-close-icon-btn);
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-filter-bar {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ margin: 16px 20px 0;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ .sub-agent-search-input {
|
|
|
+ flex: 1;
|
|
|
+ height: 36px;
|
|
|
+ background: rgba(10, 132, 255, 0.08);
|
|
|
+ border: 1px solid rgba(63, 80, 106, 0.4);
|
|
|
+ border-radius: 6px;
|
|
|
+ color: #e0e6ed;
|
|
|
+ transition: all 0.3s;
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
+ border-color: rgba(10, 132, 255, 0.5);
|
|
|
+ background: rgba(10, 132, 255, 0.12);
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.zxm-input) {
|
|
|
+ background: transparent;
|
|
|
+ color: #e0e6ed;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-filter-select {
|
|
|
+ width: 130px;
|
|
|
+ height: 36px;
|
|
|
+
|
|
|
+ :deep(.zxm-select-selector) {
|
|
|
+ background: rgba(10, 132, 255, 0.08) !important;
|
|
|
+ border: 1px solid rgba(63, 80, 106, 0.4) !important;
|
|
|
+ border-radius: 6px !important;
|
|
|
+ color: #e0e6ed;
|
|
|
+ height: 36px;
|
|
|
+ }
|
|
|
+ :deep(.zxm-select-selection-item) {
|
|
|
+ line-height: 34px !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-summary {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+ padding: 12px 20px 0;
|
|
|
+ flex-shrink: 0;
|
|
|
+ font-size: 13px;
|
|
|
+
|
|
|
+ .sub-agent-summary-label {
|
|
|
+ color: #e8edf3;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-summary-count {
|
|
|
+ color: #6a7a8a;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-create-btn {
|
|
|
+ flex-shrink: 0;
|
|
|
+ height: 32px;
|
|
|
+ border-radius: 6px;
|
|
|
+ font-size: 13px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+ margin-left: auto;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-list {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding: 12px 20px 20px;
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-track {
|
|
|
+ background: transparent;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background: rgba(63, 80, 106, 0.4);
|
|
|
+ border-radius: 3px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: rgba(63, 80, 106, 0.6);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-loading {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ padding: 80px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-item {
|
|
|
+ padding: 16px 18px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ border-radius: 8px;
|
|
|
+ border: 1px solid rgba(63, 80, 106, 0.15);
|
|
|
+ background: rgba(10, 132, 255, 0.03);
|
|
|
+ transition: all 0.25s ease;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: rgba(10, 132, 255, 0.08);
|
|
|
+ border-color: rgba(10, 132, 255, 0.25);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-name-wrapper {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-item-icon {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ background-image: var(--img-chat-options-sub-agent-icon);
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: 100% 100%;
|
|
|
+ background-position: center;
|
|
|
+ filter: drop-shadow(0 0 4px rgba(10, 132, 255, 0.3));
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-name {
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #e8edf3;
|
|
|
+ letter-spacing: 0.3px;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-actions {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-switch {
|
|
|
+ :deep(.zxm-switch) {
|
|
|
+ min-width: 36px;
|
|
|
+ height: 20px;
|
|
|
+ background: rgba(63, 80, 106, 0.5);
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ top: 2px;
|
|
|
+ left: 2px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #fff;
|
|
|
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
|
|
|
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.zxm-switch-checked {
|
|
|
+ background: rgba(10, 132, 255, 0.6);
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ left: calc(100% - 18px);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-btn {
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ cursor: pointer;
|
|
|
+ border-radius: 4px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ transition: background 0.2s;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-size: 14px 14px;
|
|
|
+ background-position: center;
|
|
|
+
|
|
|
+ &.edit-btn {
|
|
|
+ background-image: var(--img-chat-edit-icon);
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(10, 132, 255, 0.15);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &.delete-btn {
|
|
|
+ background-image: var(--img-chat-delete-icon);
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(255, 77, 79, 0.15);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-desc {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #8b949e;
|
|
|
+ line-height: 1.7;
|
|
|
+ margin-bottom: 6px;
|
|
|
+ padding-left: 34px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-detail-toggle {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #5cb8ff;
|
|
|
+ cursor: pointer;
|
|
|
+ padding-left: 34px;
|
|
|
+ width: fit-content;
|
|
|
+ transition: opacity 0.2s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ opacity: 0.8;
|
|
|
+ }
|
|
|
+
|
|
|
+ .toggle-arrow {
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border-left: 4px solid transparent;
|
|
|
+ border-right: 4px solid transparent;
|
|
|
+ border-top: 5px solid #5cb8ff;
|
|
|
+ transition: transform 0.2s;
|
|
|
+
|
|
|
+ &.expanded {
|
|
|
+ transform: rotate(180deg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-agent-detail {
|
|
|
+ margin-top: 10px;
|
|
|
+ margin-left: 34px;
|
|
|
+ padding: 12px 14px;
|
|
|
+ background: rgba(0, 0, 0, 0.12);
|
|
|
+ border: 1px solid rgba(63, 80, 106, 0.15);
|
|
|
+ border-radius: 6px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-section {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-label {
|
|
|
+ font-size: 11px;
|
|
|
+ color: #6a7a8a;
|
|
|
+ font-weight: 500;
|
|
|
+ text-transform: uppercase;
|
|
|
+ letter-spacing: 0.5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-prompt {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #c9d1d9;
|
|
|
+ line-height: 1.6;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ word-break: break-word;
|
|
|
+ max-height: 120px;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background: rgba(63, 80, 106, 0.4);
|
|
|
+ border-radius: 2px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-tools {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tool-tag {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 2px 8px;
|
|
|
+ font-size: 11px;
|
|
|
+ color: #5cb8ff;
|
|
|
+ background: rgba(10, 132, 255, 0.1);
|
|
|
+ border: 1px solid rgba(10, 132, 255, 0.2);
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ &.missing {
|
|
|
+ color: #ff7875;
|
|
|
+ background: rgba(255, 77, 79, 0.08);
|
|
|
+ border-color: rgba(255, 77, 79, 0.2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-tools-empty {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #6a7a8a;
|
|
|
+ font-style: italic;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-model {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #5cb8ff;
|
|
|
+ font-family: 'Courier New', monospace;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-time {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #8b949e;
|
|
|
+ }
|
|
|
+</style>
|