2025-04-12 18:50:34 +03:30
|
|
|
|
<template>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Header Toolbar -->
|
|
|
|
|
<v-app-bar
|
|
|
|
|
color="primary"
|
|
|
|
|
elevation="0"
|
|
|
|
|
class="ai-header"
|
|
|
|
|
height="70"
|
|
|
|
|
>
|
|
|
|
|
<div class="header-content">
|
|
|
|
|
<!-- Logo and Title -->
|
|
|
|
|
<div class="header-left">
|
|
|
|
|
<div class="logo-container">
|
|
|
|
|
<v-icon color="white" size="28">mdi-robot</v-icon>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="title-section">
|
|
|
|
|
<h1 class="app-title">هوش مصنوعی حسابیکس</h1>
|
|
|
|
|
<p class="app-subtitle">دستیار هوشمند شما</p>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Status Indicators -->
|
|
|
|
|
<div class="header-center">
|
|
|
|
|
<div class="status-indicators">
|
|
|
|
|
<!-- AI Service Status -->
|
|
|
|
|
<v-tooltip location="bottom">
|
|
|
|
|
<template v-slot:activator="{ props }">
|
|
|
|
|
<div v-bind="props" class="status-item">
|
|
|
|
|
<v-chip
|
|
|
|
|
:color="aiSettings.aiEnabled ? 'success' : 'error'"
|
|
|
|
|
size="small"
|
|
|
|
|
variant="flat"
|
|
|
|
|
class="status-chip"
|
|
|
|
|
>
|
|
|
|
|
<v-icon start size="16">
|
|
|
|
|
{{ aiSettings.aiEnabled ? 'mdi-robot' : 'mdi-robot-off' }}
|
|
|
|
|
</v-icon>
|
|
|
|
|
{{ aiSettings.aiEnabled ? 'فعال' : 'غیرفعال' }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<span>وضعیت سرویس هوش مصنوعی</span>
|
|
|
|
|
</v-tooltip>
|
|
|
|
|
|
|
|
|
|
<!-- User Balance -->
|
|
|
|
|
<v-tooltip location="bottom">
|
|
|
|
|
<template v-slot:activator="{ props }">
|
|
|
|
|
<div v-bind="props" class="status-item">
|
|
|
|
|
<v-chip
|
|
|
|
|
:color="userBalance < 1000 ? 'warning' : 'success'"
|
|
|
|
|
size="small"
|
|
|
|
|
variant="flat"
|
|
|
|
|
class="status-chip"
|
|
|
|
|
>
|
|
|
|
|
<v-icon start size="16">mdi-wallet</v-icon>
|
|
|
|
|
{{ formatBalance(userBalance) }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<span>اعتبار باقیمانده حساب شما</span>
|
|
|
|
|
</v-tooltip>
|
|
|
|
|
|
|
|
|
|
<!-- Connection Status -->
|
|
|
|
|
<v-tooltip location="bottom">
|
|
|
|
|
<template v-slot:activator="{ props }">
|
|
|
|
|
<div v-bind="props" class="status-item">
|
|
|
|
|
<v-chip
|
|
|
|
|
:color="connectionStatus.color"
|
|
|
|
|
size="small"
|
|
|
|
|
variant="flat"
|
|
|
|
|
class="status-chip"
|
|
|
|
|
>
|
|
|
|
|
<v-icon start size="16">
|
|
|
|
|
{{ connectionStatus.icon }}
|
|
|
|
|
</v-icon>
|
|
|
|
|
{{ connectionStatus.text }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<span>وضعیت اتصال به سرور</span>
|
|
|
|
|
</v-tooltip>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Action Buttons -->
|
|
|
|
|
<div class="header-right">
|
|
|
|
|
<v-tooltip location="bottom">
|
|
|
|
|
<template v-slot:activator="{ props }">
|
|
|
|
|
<v-btn
|
|
|
|
|
v-bind="props"
|
|
|
|
|
icon
|
|
|
|
|
@click="showConversationsDialog = true"
|
|
|
|
|
class="action-btn"
|
|
|
|
|
color="white"
|
|
|
|
|
variant="text"
|
|
|
|
|
>
|
|
|
|
|
<v-icon>mdi-archive</v-icon>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</template>
|
|
|
|
|
<span>مشاهده آرشیو گفتگوها</span>
|
|
|
|
|
</v-tooltip>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-app-bar>
|
|
|
|
|
|
|
|
|
|
<!-- Main Content -->
|
|
|
|
|
<div class="main-container">
|
|
|
|
|
<!-- Info Cards Section -->
|
|
|
|
|
<div class="info-section" v-if="aiSettings.aiEnabled">
|
|
|
|
|
<div class="info-cards">
|
|
|
|
|
<!-- Pricing Card -->
|
|
|
|
|
<v-card class="info-card pricing-card" elevation="1">
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<div class="pricing-row">
|
|
|
|
|
<v-icon color="info" size="16" class="pricing-icon">mdi-currency-usd</v-icon>
|
|
|
|
|
<div class="pricing-info">
|
|
|
|
|
<span class="pricing-label">قیمت:</span>
|
|
|
|
|
<span class="pricing-value">{{ aiSettings.inputTokenPrice.toLocaleString('fa-IR') }} / {{ aiSettings.outputTokenPrice.toLocaleString('fa-IR') }}</span>
|
|
|
|
|
<span class="pricing-unit">ریال/1000 توکن</span>
|
2025-07-18 02:30:04 +03:30
|
|
|
|
</div>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
</div>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Usage Stats Card -->
|
|
|
|
|
<v-card class="info-card stats-card" elevation="1" v-if="userMessages.length > 0">
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<div class="stats-row">
|
|
|
|
|
<v-icon color="success" size="16" class="stats-icon">mdi-chart-line</v-icon>
|
|
|
|
|
<div class="stats-info">
|
|
|
|
|
<span class="stats-label">استفاده:</span>
|
|
|
|
|
<span class="stats-value">{{ userMessages.length }} پیام • {{ usageStats.totalTokens.toLocaleString('fa-IR') }} توکن • {{ usageStats.totalCost.toLocaleString('fa-IR') }} ریال</span>
|
2025-07-18 02:30:04 +03:30
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
</v-card>
|
|
|
|
|
</div>
|
2025-07-18 02:30:04 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
<!-- Chat Container -->
|
|
|
|
|
<div class="chat-section">
|
|
|
|
|
<v-card class="chat-container" elevation="3">
|
|
|
|
|
<!-- Chat Header -->
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<div class="chat-header" v-if="currentConversation">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="conversation-info">
|
|
|
|
|
<div class="conversation-title">
|
|
|
|
|
<v-icon color="primary" size="20">mdi-chat</v-icon>
|
|
|
|
|
<span class="title-text">{{ currentConversation.title }}</span>
|
|
|
|
|
<v-chip size="small" variant="outlined" class="category-chip">
|
|
|
|
|
{{ currentConversation.category }}
|
|
|
|
|
</v-chip>
|
2025-07-18 02:30:04 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-btn
|
|
|
|
|
size="small"
|
|
|
|
|
variant="text"
|
|
|
|
|
color="primary"
|
|
|
|
|
@click="newConversation"
|
|
|
|
|
class="new-chat-btn"
|
|
|
|
|
>
|
|
|
|
|
<v-icon start size="16">mdi-plus</v-icon>
|
|
|
|
|
گفتگوی جدید
|
|
|
|
|
</v-btn>
|
2025-07-18 02:30:04 +03:30
|
|
|
|
</div>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Messages Area -->
|
|
|
|
|
<div class="messages-area">
|
2025-05-04 01:07:39 +03:30
|
|
|
|
<div class="messages-container" ref="messagesContainer">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Welcome Message -->
|
2025-05-04 01:07:39 +03:30
|
|
|
|
<div class="message ai-message" v-if="displayWelcome">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="message-avatar">
|
|
|
|
|
<v-avatar color="primary" size="40">
|
|
|
|
|
<v-icon color="white" size="20">mdi-robot</v-icon>
|
|
|
|
|
</v-avatar>
|
|
|
|
|
</div>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
<div class="message-content">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="message-text" v-html="renderMarkdown(displayWelcome)"></div>
|
|
|
|
|
<div class="message-time">{{ formatTime(new Date()) }}</div>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- User and AI Messages -->
|
2025-05-04 01:07:39 +03:30
|
|
|
|
<template v-for="(message, index) in userMessages" :key="index">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- User Message -->
|
2025-05-04 01:07:39 +03:30
|
|
|
|
<div class="message user-message" v-if="typeof message === 'string'">
|
|
|
|
|
<div class="message-content">
|
|
|
|
|
<div class="message-text">{{ message }}</div>
|
2025-07-18 02:30:04 +03:30
|
|
|
|
<div class="message-time">{{ formatTime(new Date()) }}</div>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="message-avatar">
|
|
|
|
|
<v-avatar color="grey lighten-2" size="40">
|
|
|
|
|
<v-icon color="grey darken-1" size="20">mdi-account</v-icon>
|
|
|
|
|
</v-avatar>
|
|
|
|
|
</div>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- AI Message -->
|
2025-05-04 01:07:39 +03:30
|
|
|
|
<div class="message ai-message" v-else-if="message && message.isAI">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="message-avatar">
|
|
|
|
|
<v-avatar
|
|
|
|
|
:color="message.text && message.text.startsWith('خطا:') ? 'error' : 'primary'"
|
|
|
|
|
size="40"
|
|
|
|
|
>
|
|
|
|
|
<v-icon color="white" size="20">
|
|
|
|
|
{{ message.text && message.text.startsWith('خطا:') ? 'mdi-alert-circle' : 'mdi-robot' }}
|
|
|
|
|
</v-icon>
|
|
|
|
|
</v-avatar>
|
|
|
|
|
</div>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<div class="message-content" :class="{
|
2025-07-19 16:34:23 +03:30
|
|
|
|
'error-message': message.text && message.text.startsWith('خطا:'),
|
|
|
|
|
'success-message': message.text && !message.text.startsWith('خطا:')
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}">
|
|
|
|
|
<div class="message-text" v-html="renderMarkdown(message.text)"></div>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Debug Button -->
|
|
|
|
|
<div class="debug-section" v-if="message.debug_info">
|
|
|
|
|
<v-btn
|
|
|
|
|
size="small"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
color="info"
|
|
|
|
|
@click="openDebugDialog(message.debug_info, index)"
|
|
|
|
|
class="debug-btn"
|
|
|
|
|
prepend-icon="mdi-bug"
|
|
|
|
|
>
|
|
|
|
|
<span>دیباگ</span>
|
|
|
|
|
<v-chip
|
|
|
|
|
size="x-small"
|
|
|
|
|
color="info"
|
|
|
|
|
variant="tonal"
|
|
|
|
|
class="debug-count"
|
|
|
|
|
v-if="getDebugInfoCount(message.debug_info) > 0"
|
|
|
|
|
>
|
|
|
|
|
{{ getDebugInfoCount(message.debug_info) }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
</v-btn>
|
2025-07-19 13:49:33 +03:30
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Charge Button -->
|
|
|
|
|
<div class="charge-section" v-if="message.showChargeButton">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<v-btn
|
|
|
|
|
color="success"
|
|
|
|
|
variant="elevated"
|
|
|
|
|
size="small"
|
|
|
|
|
@click="goToChargePage"
|
|
|
|
|
prepend-icon="mdi-credit-card"
|
|
|
|
|
class="charge-btn"
|
|
|
|
|
>
|
|
|
|
|
شارژ حساب
|
|
|
|
|
</v-btn>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-18 02:30:04 +03:30
|
|
|
|
<div class="message-time">{{ formatTime(new Date()) }}</div>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Typing Indicator -->
|
2025-05-04 01:07:39 +03:30
|
|
|
|
<div class="message ai-message" v-if="isTyping">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="message-avatar">
|
|
|
|
|
<v-avatar color="primary" size="40">
|
|
|
|
|
<v-icon color="white" size="20">mdi-robot</v-icon>
|
|
|
|
|
</v-avatar>
|
|
|
|
|
</div>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
<div class="message-content">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="typing-indicator">
|
|
|
|
|
<span></span>
|
|
|
|
|
<span></span>
|
|
|
|
|
<span></span>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Suggestions -->
|
|
|
|
|
<div class="suggestions-section" v-if="userMessages.length === 0 && aiSettings.aiEnabled">
|
|
|
|
|
<div class="suggestions-title">
|
|
|
|
|
<v-icon color="primary" size="20">mdi-lightbulb</v-icon>
|
|
|
|
|
<span>پیشنهادات</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="suggestions-grid">
|
2025-07-18 02:30:04 +03:30
|
|
|
|
<v-chip
|
|
|
|
|
v-for="suggestion in suggestions"
|
|
|
|
|
:key="suggestion"
|
2025-07-19 16:34:23 +03:30
|
|
|
|
size="small"
|
|
|
|
|
variant="outlined"
|
2025-07-18 02:30:04 +03:30
|
|
|
|
@click="useSuggestion(suggestion)"
|
|
|
|
|
class="suggestion-chip"
|
2025-07-18 06:29:39 +03:30
|
|
|
|
color="primary"
|
2025-07-18 02:30:04 +03:30
|
|
|
|
>
|
|
|
|
|
{{ suggestion }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
</div>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
</div>
|
|
|
|
|
</v-card>
|
|
|
|
|
</div>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Input Section -->
|
|
|
|
|
<div class="input-section">
|
|
|
|
|
<div class="input-container">
|
|
|
|
|
<v-text-field
|
|
|
|
|
v-model="userMessage"
|
|
|
|
|
class="message-input"
|
|
|
|
|
:placeholder="aiSettings.aiEnabled ? 'پیام خود را بنویسید...' : 'سرویس هوش مصنوعی غیرفعال است'"
|
|
|
|
|
hide-details="auto"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
@keyup.enter="sendMessage"
|
|
|
|
|
:disabled="isLoading || !aiSettings.aiEnabled"
|
|
|
|
|
ref="messageInput"
|
|
|
|
|
autofocus
|
|
|
|
|
rounded
|
|
|
|
|
density="comfortable"
|
|
|
|
|
>
|
|
|
|
|
<template #append-inner>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<v-btn
|
|
|
|
|
color="primary"
|
2025-07-18 07:15:33 +03:30
|
|
|
|
:disabled="isLoading || !userMessage.trim() || !aiSettings.aiEnabled"
|
2025-07-18 06:29:39 +03:30
|
|
|
|
@click="sendMessage"
|
|
|
|
|
icon
|
2025-07-19 16:34:23 +03:30
|
|
|
|
class="send-btn"
|
2025-07-18 06:29:39 +03:30
|
|
|
|
>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-icon class="send-icon">mdi-send</v-icon>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</v-btn>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
</template>
|
|
|
|
|
</v-text-field>
|
|
|
|
|
</div>
|
2025-05-04 01:07:39 +03:30
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Conversations Dialog -->
|
|
|
|
|
<v-dialog v-model="showConversationsDialog" max-width="900px" persistent>
|
|
|
|
|
<v-card class="conversations-dialog">
|
|
|
|
|
<v-card-title class="dialog-header">
|
|
|
|
|
<div class="dialog-title">
|
|
|
|
|
<v-icon color="primary" size="24">mdi-archive</v-icon>
|
|
|
|
|
<span>آرشیو گفتگوها</span>
|
|
|
|
|
</div>
|
|
|
|
|
<v-btn icon @click="showConversationsDialog = false" variant="text">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<v-icon>mdi-close</v-icon>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-card-text class="dialog-content">
|
|
|
|
|
<!-- Filters -->
|
|
|
|
|
<div class="filters-section">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<v-text-field
|
|
|
|
|
v-model="searchTerm"
|
|
|
|
|
placeholder="جستجو در گفتگوها..."
|
|
|
|
|
prepend-inner-icon="mdi-magnify"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
density="compact"
|
|
|
|
|
hide-details
|
2025-07-19 16:34:23 +03:30
|
|
|
|
class="search-field"
|
2025-07-18 06:29:39 +03:30
|
|
|
|
@input="searchConversations"
|
|
|
|
|
></v-text-field>
|
|
|
|
|
<v-select
|
|
|
|
|
v-model="selectedCategory"
|
|
|
|
|
:items="categories"
|
|
|
|
|
placeholder="دستهبندی"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
density="compact"
|
|
|
|
|
hide-details
|
2025-07-19 16:34:23 +03:30
|
|
|
|
class="category-field"
|
2025-07-18 06:29:39 +03:30
|
|
|
|
@update:model-value="filterByCategory"
|
|
|
|
|
></v-select>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Conversations List -->
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<div class="conversations-list">
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-list class="conversations-items">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<v-list-item
|
|
|
|
|
v-for="conversation in filteredConversations"
|
|
|
|
|
:key="conversation.id"
|
|
|
|
|
class="conversation-item"
|
2025-07-19 16:34:23 +03:30
|
|
|
|
@click="loadConversation(conversation)"
|
2025-07-18 06:29:39 +03:30
|
|
|
|
>
|
|
|
|
|
<template #prepend>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-avatar color="primary" size="48">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<v-icon color="white">mdi-chat</v-icon>
|
|
|
|
|
</v-avatar>
|
|
|
|
|
</template>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-list-item-title class="conversation-title">
|
|
|
|
|
{{ conversation.title }}
|
|
|
|
|
</v-list-item-title>
|
|
|
|
|
|
|
|
|
|
<v-list-item-subtitle class="conversation-details">
|
|
|
|
|
<div class="conversation-meta">
|
|
|
|
|
<v-chip size="x-small" variant="tonal" color="primary">
|
|
|
|
|
{{ conversation.category }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
<span class="conversation-date">{{ conversation.updatedAt }}</span>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</div>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<div class="conversation-stats">
|
|
|
|
|
{{ conversation.messageCount || 0 }} پیام •
|
|
|
|
|
{{ (conversation.stats?.totalTokens || 0).toLocaleString('fa-IR') }} توکن •
|
|
|
|
|
{{ (conversation.stats?.totalCost || 0).toLocaleString('fa-IR') }} ریال
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</div>
|
|
|
|
|
</v-list-item-subtitle>
|
|
|
|
|
|
|
|
|
|
<template #append>
|
|
|
|
|
<v-btn
|
|
|
|
|
variant="text"
|
|
|
|
|
size="small"
|
|
|
|
|
color="error"
|
|
|
|
|
@click.stop="deleteConversation(conversation)"
|
|
|
|
|
class="delete-btn"
|
|
|
|
|
icon
|
|
|
|
|
>
|
|
|
|
|
<v-icon size="18">mdi-delete</v-icon>
|
|
|
|
|
<v-tooltip activator="parent" location="top">حذف گفتگو</v-tooltip>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</template>
|
|
|
|
|
</v-list-item>
|
|
|
|
|
</v-list>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-card-actions class="dialog-actions">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<v-spacer></v-spacer>
|
|
|
|
|
<v-btn
|
|
|
|
|
color="primary"
|
|
|
|
|
@click="newConversation"
|
|
|
|
|
prepend-icon="mdi-plus"
|
2025-07-19 16:34:23 +03:30
|
|
|
|
variant="elevated"
|
2025-07-18 06:29:39 +03:30
|
|
|
|
>
|
|
|
|
|
گفتگوی جدید
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-card-actions>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-dialog>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Delete Confirmation Dialog -->
|
|
|
|
|
<v-dialog v-model="showDeleteDialog" max-width="450px" persistent>
|
|
|
|
|
<v-card class="delete-dialog">
|
|
|
|
|
<v-card-title class="delete-header">
|
|
|
|
|
<v-icon color="error" size="24">mdi-delete</v-icon>
|
|
|
|
|
<span>حذف گفتگو</span>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
</v-card-title>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-card-text class="delete-content">
|
|
|
|
|
<p class="delete-message">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
آیا مطمئن هستید که میخواهید گفتگوی
|
|
|
|
|
<strong>"{{ conversationToDelete?.title }}"</strong>
|
|
|
|
|
را حذف کنید؟
|
|
|
|
|
</p>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<p class="delete-warning">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
این عملیات قابل بازگشت نیست و گفتگو از لیست شما حذف خواهد شد.
|
|
|
|
|
</p>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-card-actions class="delete-actions">
|
2025-07-18 06:29:39 +03:30
|
|
|
|
<v-spacer></v-spacer>
|
|
|
|
|
<v-btn
|
|
|
|
|
variant="text"
|
|
|
|
|
@click="showDeleteDialog = false"
|
|
|
|
|
color="grey"
|
|
|
|
|
>
|
|
|
|
|
انصراف
|
|
|
|
|
</v-btn>
|
|
|
|
|
<v-btn
|
|
|
|
|
color="error"
|
|
|
|
|
@click="confirmDeleteConversation"
|
|
|
|
|
:loading="isLoading"
|
|
|
|
|
prepend-icon="mdi-delete"
|
2025-07-19 16:34:23 +03:30
|
|
|
|
variant="elevated"
|
2025-07-18 06:29:39 +03:30
|
|
|
|
>
|
|
|
|
|
حذف
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-card-actions>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-dialog>
|
2025-07-18 19:59:35 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<!-- Person Info Dialog -->
|
|
|
|
|
<v-dialog v-model="showPersonInfo" max-width="1000px" persistent>
|
|
|
|
|
<v-card class="person-dialog">
|
|
|
|
|
<v-card-title class="dialog-header">
|
|
|
|
|
<div class="dialog-title">
|
|
|
|
|
<v-icon color="primary" size="24">mdi-account</v-icon>
|
|
|
|
|
<span>اطلاعات شخص</span>
|
|
|
|
|
</div>
|
|
|
|
|
<v-btn icon @click="showPersonInfo = false" variant="text">
|
2025-07-18 19:59:35 +03:30
|
|
|
|
<v-icon>mdi-close</v-icon>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
<v-card-text class="dialog-content">
|
2025-07-18 19:59:35 +03:30
|
|
|
|
<PersonInfo
|
|
|
|
|
:person="selectedPerson"
|
|
|
|
|
:transactions="personTransactions"
|
|
|
|
|
/>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-dialog>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
<!-- Debug Dialog -->
|
|
|
|
|
<v-dialog v-model="showDebugDialog" max-width="1400px" fullscreen persistent>
|
|
|
|
|
<v-card class="debug-dialog">
|
|
|
|
|
<!-- Debug Header -->
|
|
|
|
|
<v-card-title class="debug-header">
|
|
|
|
|
<div class="debug-title-section">
|
|
|
|
|
<div class="debug-icon">
|
|
|
|
|
<v-icon color="white" size="28">mdi-bug</v-icon>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="debug-info">
|
|
|
|
|
<h2 class="debug-title">اطلاعات دیباگ</h2>
|
|
|
|
|
<p class="debug-subtitle">جزئیات کامل عملیات و نتایج</p>
|
|
|
|
|
</div>
|
|
|
|
|
<v-chip
|
|
|
|
|
size="small"
|
|
|
|
|
color="info"
|
|
|
|
|
variant="flat"
|
|
|
|
|
class="debug-count"
|
|
|
|
|
v-if="currentDebugInfo && getDebugInfoCount(currentDebugInfo) > 0"
|
|
|
|
|
>
|
|
|
|
|
{{ getDebugInfoCount(currentDebugInfo) }} آیتم
|
|
|
|
|
</v-chip>
|
|
|
|
|
</div>
|
|
|
|
|
<v-btn
|
|
|
|
|
icon
|
|
|
|
|
@click="showDebugDialog = false"
|
|
|
|
|
color="white"
|
|
|
|
|
variant="text"
|
|
|
|
|
class="close-btn"
|
|
|
|
|
>
|
|
|
|
|
<v-icon>mdi-close</v-icon>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
|
|
|
|
|
<!-- Debug Content -->
|
|
|
|
|
<v-card-text class="debug-content" v-if="currentDebugInfo">
|
|
|
|
|
<!-- Main Cards -->
|
|
|
|
|
<div class="debug-main-cards">
|
|
|
|
|
<!-- Operation Type Card -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.operation_type"
|
|
|
|
|
class="debug-main-card operation-card"
|
|
|
|
|
elevation="3"
|
|
|
|
|
>
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
<div class="card-icon">
|
|
|
|
|
<v-icon color="white" size="24">mdi-cog</v-icon>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<h3 class="card-title">نوع عملیات</h3>
|
|
|
|
|
<v-chip
|
|
|
|
|
:color="getOperationTypeColor(currentDebugInfo.operation_type)"
|
|
|
|
|
size="small"
|
|
|
|
|
variant="flat"
|
|
|
|
|
class="operation-chip"
|
|
|
|
|
>
|
|
|
|
|
{{ getOperationTypeText(currentDebugInfo.operation_type) }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Current Step Card -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.current_step"
|
|
|
|
|
class="debug-main-card status-card"
|
|
|
|
|
elevation="3"
|
|
|
|
|
>
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
<div class="card-icon">
|
|
|
|
|
<v-icon color="white" size="24">mdi-play-circle</v-icon>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<h3 class="card-title">مرحله فعلی</h3>
|
|
|
|
|
<p class="card-text">{{ currentDebugInfo.current_step }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Attempt Count Card -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.attempt_count"
|
|
|
|
|
class="debug-main-card attempt-card"
|
|
|
|
|
elevation="3"
|
|
|
|
|
>
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
<div class="card-icon">
|
|
|
|
|
<v-icon color="white" size="24">mdi-repeat</v-icon>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<h3 class="card-title">تعداد تلاش</h3>
|
|
|
|
|
<div class="attempt-progress">
|
|
|
|
|
<v-progress-linear
|
|
|
|
|
:model-value="(currentDebugInfo.attempt_count / currentDebugInfo.max_attempts) * 100"
|
|
|
|
|
color="warning"
|
|
|
|
|
height="10"
|
|
|
|
|
class="progress-bar"
|
|
|
|
|
></v-progress-linear>
|
|
|
|
|
<span class="attempt-text">
|
|
|
|
|
{{ currentDebugInfo.attempt_count }} از {{ currentDebugInfo.max_attempts }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Next Action Card -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.next_action"
|
|
|
|
|
class="debug-main-card next-card"
|
|
|
|
|
elevation="3"
|
|
|
|
|
>
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
<div class="card-icon">
|
|
|
|
|
<v-icon color="white" size="24">mdi-arrow-right</v-icon>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-content">
|
|
|
|
|
<h3 class="card-title">مرحله بعدی</h3>
|
|
|
|
|
<p class="card-text">{{ currentDebugInfo.next_action }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Results Section -->
|
|
|
|
|
<div class="debug-results-section">
|
|
|
|
|
<!-- Tool Commands -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.tool_commands && currentDebugInfo.tool_commands.length > 0"
|
|
|
|
|
class="debug-section-card"
|
|
|
|
|
elevation="2"
|
|
|
|
|
>
|
|
|
|
|
<v-card-title class="section-title">
|
|
|
|
|
<v-icon color="primary" size="20" class="mr-2">mdi-tools</v-icon>
|
|
|
|
|
دستورات ابزار یافت شده
|
|
|
|
|
<v-chip size="small" color="primary" variant="tonal" class="ml-2">
|
|
|
|
|
{{ currentDebugInfo.tool_commands.length }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="section-content">
|
|
|
|
|
<div class="tools-grid">
|
|
|
|
|
<div
|
|
|
|
|
v-for="(command, cmdIndex) in currentDebugInfo.tool_commands"
|
|
|
|
|
:key="cmdIndex"
|
|
|
|
|
class="tool-item"
|
|
|
|
|
>
|
|
|
|
|
<div class="tool-header">
|
|
|
|
|
<v-icon color="primary" size="18" class="mr-2">mdi-wrench</v-icon>
|
|
|
|
|
<span class="tool-name">{{ command.tool }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="tool-actions">
|
|
|
|
|
<v-btn
|
|
|
|
|
size="small"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
color="info"
|
|
|
|
|
@click="toggleJsonView(`tool-${cmdIndex}`)"
|
|
|
|
|
class="view-btn"
|
|
|
|
|
>
|
|
|
|
|
<v-icon size="16" class="mr-1">mdi-code-json</v-icon>
|
|
|
|
|
نمایش پارامترها
|
|
|
|
|
</v-btn>
|
|
|
|
|
</div>
|
|
|
|
|
<v-expand-transition>
|
|
|
|
|
<div v-show="expandedJsonViews[`tool-${cmdIndex}`]" class="json-container">
|
|
|
|
|
<pre class="json-content">{{ JSON.stringify(command.params, null, 2) }}</pre>
|
|
|
|
|
</div>
|
|
|
|
|
</v-expand-transition>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Execution Results -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.execution_results && currentDebugInfo.execution_results.length > 0"
|
|
|
|
|
class="debug-section-card"
|
|
|
|
|
elevation="2"
|
|
|
|
|
>
|
|
|
|
|
<v-card-title class="section-title">
|
|
|
|
|
<v-icon color="success" size="20" class="mr-2">mdi-playlist-check</v-icon>
|
|
|
|
|
نتایج اجرای چندمرحلهای
|
|
|
|
|
<v-chip size="small" color="success" variant="tonal" class="ml-2">
|
|
|
|
|
{{ currentDebugInfo.execution_results.length }}
|
|
|
|
|
</v-chip>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="section-content">
|
|
|
|
|
<div class="execution-timeline">
|
|
|
|
|
<div
|
|
|
|
|
v-for="(result, resultIndex) in currentDebugInfo.execution_results"
|
|
|
|
|
:key="resultIndex"
|
|
|
|
|
class="timeline-item"
|
|
|
|
|
>
|
|
|
|
|
<div class="timeline-marker">
|
|
|
|
|
<v-icon color="success" size="16">mdi-check-circle</v-icon>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="timeline-content">
|
|
|
|
|
<div class="timeline-header">
|
|
|
|
|
<span class="timeline-title">مرحله {{ resultIndex + 1 }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="timeline-actions">
|
|
|
|
|
<v-btn
|
|
|
|
|
size="small"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
color="info"
|
|
|
|
|
@click="toggleJsonView(`execution-${resultIndex}`)"
|
|
|
|
|
class="view-btn"
|
|
|
|
|
>
|
|
|
|
|
<v-icon size="16" class="mr-1">mdi-code-json</v-icon>
|
|
|
|
|
نمایش نتیجه
|
|
|
|
|
</v-btn>
|
|
|
|
|
</div>
|
|
|
|
|
<v-expand-transition>
|
|
|
|
|
<div v-show="expandedJsonViews[`execution-${resultIndex}`]" class="json-container">
|
|
|
|
|
<pre class="json-content">{{ JSON.stringify(result, null, 2) }}</pre>
|
|
|
|
|
</div>
|
|
|
|
|
</v-expand-transition>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- JSON Response -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.json_response"
|
|
|
|
|
class="debug-section-card"
|
|
|
|
|
elevation="2"
|
|
|
|
|
>
|
|
|
|
|
<v-card-title class="section-title">
|
|
|
|
|
<v-icon color="info" size="20" class="mr-2">mdi-code-json</v-icon>
|
|
|
|
|
پاسخ JSON
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="section-content">
|
|
|
|
|
<v-btn
|
|
|
|
|
size="small"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
color="info"
|
|
|
|
|
@click="toggleJsonView('json-response')"
|
|
|
|
|
class="view-btn"
|
|
|
|
|
>
|
|
|
|
|
<v-icon size="16" class="mr-1">mdi-eye</v-icon>
|
|
|
|
|
نمایش JSON
|
|
|
|
|
</v-btn>
|
|
|
|
|
<v-expand-transition>
|
|
|
|
|
<div v-show="expandedJsonViews['json-response']" class="json-container">
|
|
|
|
|
<pre class="json-content">{{ JSON.stringify(currentDebugInfo.json_response, null, 2) }}</pre>
|
|
|
|
|
</div>
|
|
|
|
|
</v-expand-transition>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Final Data -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.final_data"
|
|
|
|
|
class="debug-section-card"
|
|
|
|
|
elevation="2"
|
|
|
|
|
>
|
|
|
|
|
<v-card-title class="section-title">
|
|
|
|
|
<v-icon color="success" size="20" class="mr-2">mdi-database</v-icon>
|
|
|
|
|
دادههای نهایی
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="section-content">
|
|
|
|
|
<v-btn
|
|
|
|
|
size="small"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
color="info"
|
|
|
|
|
@click="toggleJsonView('final-data')"
|
|
|
|
|
class="view-btn"
|
|
|
|
|
>
|
|
|
|
|
<v-icon size="16" class="mr-1">mdi-eye</v-icon>
|
|
|
|
|
نمایش دادهها
|
|
|
|
|
</v-btn>
|
|
|
|
|
<v-expand-transition>
|
|
|
|
|
<div v-show="expandedJsonViews['final-data']" class="json-container">
|
|
|
|
|
<pre class="json-content">{{ JSON.stringify(currentDebugInfo.final_data, null, 2) }}</pre>
|
|
|
|
|
</div>
|
|
|
|
|
</v-expand-transition>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- AI Response -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.ai_response"
|
|
|
|
|
class="debug-section-card"
|
|
|
|
|
elevation="2"
|
|
|
|
|
>
|
|
|
|
|
<v-card-title class="section-title">
|
|
|
|
|
<v-icon color="primary" size="20" class="mr-2">mdi-robot</v-icon>
|
|
|
|
|
پاسخ هوش مصنوعی
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="section-content">
|
|
|
|
|
<v-btn
|
|
|
|
|
size="small"
|
|
|
|
|
variant="outlined"
|
|
|
|
|
color="info"
|
|
|
|
|
@click="toggleJsonView('ai-response')"
|
|
|
|
|
class="view-btn"
|
|
|
|
|
>
|
|
|
|
|
<v-icon size="16" class="mr-1">mdi-eye</v-icon>
|
|
|
|
|
نمایش پاسخ
|
|
|
|
|
</v-btn>
|
|
|
|
|
<v-expand-transition>
|
|
|
|
|
<div v-show="expandedJsonViews['ai-response']" class="ai-response-container">
|
|
|
|
|
<div class="ai-response-content">{{ currentDebugInfo.ai_response }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</v-expand-transition>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Final Result -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.final_result"
|
|
|
|
|
class="debug-section-card success-card"
|
|
|
|
|
elevation="2"
|
|
|
|
|
>
|
|
|
|
|
<v-card-title class="section-title">
|
|
|
|
|
<v-icon color="success" size="20" class="mr-2">mdi-check-circle</v-icon>
|
|
|
|
|
نتیجه نهایی
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="section-content">
|
|
|
|
|
<div class="final-result-content">
|
|
|
|
|
<p class="result-text">{{ currentDebugInfo.final_result }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
|
|
|
|
|
<!-- Error -->
|
|
|
|
|
<v-card
|
|
|
|
|
v-if="currentDebugInfo.error"
|
|
|
|
|
class="debug-section-card error-card"
|
|
|
|
|
elevation="2"
|
|
|
|
|
>
|
|
|
|
|
<v-card-title class="section-title">
|
|
|
|
|
<v-icon color="error" size="20" class="mr-2">mdi-alert-circle</v-icon>
|
|
|
|
|
خطا
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text class="section-content">
|
|
|
|
|
<div class="error-content">
|
|
|
|
|
<p class="error-text">{{ currentDebugInfo.error }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
</div>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-dialog>
|
2025-04-12 18:50:34 +03:30
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-07-18 06:29:39 +03:30
|
|
|
|
import { marked } from 'marked';
|
|
|
|
|
import DOMPurify from 'dompurify';
|
|
|
|
|
import axios from 'axios';
|
2025-07-18 19:59:35 +03:30
|
|
|
|
import PersonInfo from '@/components/PersonInfo.vue';
|
2025-07-18 02:30:04 +03:30
|
|
|
|
|
2025-04-12 18:50:34 +03:30
|
|
|
|
export default {
|
|
|
|
|
name: 'WizardHome',
|
2025-07-18 19:59:35 +03:30
|
|
|
|
components: {
|
|
|
|
|
PersonInfo
|
|
|
|
|
},
|
2025-04-12 18:50:34 +03:30
|
|
|
|
data() {
|
|
|
|
|
return {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
// User Input
|
2025-05-04 01:07:39 +03:30
|
|
|
|
userMessage: '',
|
2025-07-18 06:29:39 +03:30
|
|
|
|
isLoading: false,
|
|
|
|
|
isTyping: false,
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
// Messages
|
|
|
|
|
userMessages: [],
|
|
|
|
|
displayWelcome: '',
|
|
|
|
|
|
|
|
|
|
// AI Settings
|
2025-07-18 02:30:04 +03:30
|
|
|
|
aiSettings: {
|
|
|
|
|
aiEnabled: false,
|
2025-07-18 06:29:39 +03:30
|
|
|
|
aiAgentSource: '',
|
|
|
|
|
aiModel: '',
|
2025-07-18 02:30:04 +03:30
|
|
|
|
inputTokenPrice: 0,
|
|
|
|
|
outputTokenPrice: 0,
|
|
|
|
|
aiPrompt: ''
|
|
|
|
|
},
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
// Status
|
2025-07-18 06:29:39 +03:30
|
|
|
|
connectionStatus: {
|
|
|
|
|
color: 'grey',
|
|
|
|
|
icon: 'mdi-help-circle',
|
|
|
|
|
text: 'در حال بررسی...'
|
|
|
|
|
},
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
// User Data
|
|
|
|
|
userBalance: 0,
|
|
|
|
|
|
|
|
|
|
// Conversations
|
2025-07-18 06:29:39 +03:30
|
|
|
|
currentConversation: null,
|
|
|
|
|
showConversationsDialog: false,
|
|
|
|
|
conversations: [],
|
|
|
|
|
filteredConversations: [],
|
|
|
|
|
searchTerm: '',
|
|
|
|
|
selectedCategory: '',
|
|
|
|
|
categories: [],
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
// Delete Dialog
|
2025-07-18 06:29:39 +03:30
|
|
|
|
showDeleteDialog: false,
|
2025-07-18 19:59:35 +03:30
|
|
|
|
conversationToDelete: null,
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
// Person Info
|
2025-07-18 19:59:35 +03:30
|
|
|
|
selectedPerson: null,
|
|
|
|
|
personTransactions: [],
|
|
|
|
|
showPersonInfo: false,
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
// Debug
|
|
|
|
|
expandedJsonViews: {},
|
|
|
|
|
showDebugDialog: false,
|
|
|
|
|
currentDebugInfo: null,
|
|
|
|
|
|
|
|
|
|
// Suggestions
|
|
|
|
|
suggestions: [
|
|
|
|
|
'چگونه سند حسابداری ثبت کنم؟',
|
|
|
|
|
'راهنمای انبارداری',
|
|
|
|
|
'ثبت خرید و فروش',
|
|
|
|
|
'گزارشهای مالی',
|
|
|
|
|
'تنظیمات کاربران',
|
|
|
|
|
'اطلاعات اشخاص',
|
|
|
|
|
'جستجو در اشخاص',
|
|
|
|
|
'موجودی اشخاص',
|
|
|
|
|
'شخص علی اضافه کن',
|
|
|
|
|
'تلفن 09123456789 را برای محسن اضافه کن',
|
|
|
|
|
'شخص احمد را حذف کن'
|
|
|
|
|
]
|
2025-07-18 06:29:39 +03:30
|
|
|
|
};
|
2025-07-18 02:30:04 +03:30
|
|
|
|
},
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
2025-07-18 02:30:04 +03:30
|
|
|
|
computed: {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
usageStats() {
|
|
|
|
|
let totalTokens = 0;
|
|
|
|
|
let totalCost = 0;
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.userMessages.forEach((msg) => {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
if (msg && msg.isAI && msg.usage) {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
const promptTokens = msg.usage.prompt_tokens || 0;
|
|
|
|
|
const completionTokens = msg.usage.completion_tokens || 0;
|
|
|
|
|
const messageTokens = promptTokens + completionTokens;
|
|
|
|
|
const messageCost = msg.cost?.total_cost || 0;
|
|
|
|
|
|
|
|
|
|
totalTokens += messageTokens;
|
|
|
|
|
totalCost += messageCost;
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
return { totalTokens, totalCost };
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
},
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
2025-05-04 01:07:39 +03:30
|
|
|
|
watch: {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
searchTerm() {
|
|
|
|
|
this.searchConversations();
|
2025-05-04 01:07:39 +03:30
|
|
|
|
},
|
2025-07-18 06:29:39 +03:30
|
|
|
|
selectedCategory() {
|
|
|
|
|
this.filterByCategory();
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
|
|
|
|
},
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
2025-07-18 06:29:39 +03:30
|
|
|
|
async mounted() {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
await this.initializeApp();
|
2025-07-18 06:29:39 +03:30
|
|
|
|
},
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
2025-04-12 18:50:34 +03:30
|
|
|
|
methods: {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
// Initialization
|
|
|
|
|
async initializeApp() {
|
|
|
|
|
try {
|
|
|
|
|
await Promise.all([
|
|
|
|
|
this.loadSettings(),
|
|
|
|
|
this.checkConnection(),
|
|
|
|
|
this.loadConversations(),
|
|
|
|
|
this.loadBalance()
|
|
|
|
|
]);
|
|
|
|
|
this.setWelcomeMessage();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در راهاندازی برنامه:', error);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Settings & Status
|
2025-07-18 06:29:39 +03:30
|
|
|
|
async loadSettings() {
|
2025-07-18 02:30:04 +03:30
|
|
|
|
try {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
const response = await axios.get('/api/wizard/settings');
|
2025-07-18 02:30:04 +03:30
|
|
|
|
if (response.data.success) {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
this.aiSettings = response.data.settings;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
console.error('خطا در بارگذاری تنظیمات:', error);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
},
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
2025-07-18 06:29:39 +03:30
|
|
|
|
async checkConnection() {
|
2025-07-18 02:30:04 +03:30
|
|
|
|
try {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
const response = await axios.get('/api/wizard/status');
|
2025-07-18 02:30:04 +03:30
|
|
|
|
if (response.data.success) {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
const status = response.data.status;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.updateConnectionStatus(status);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
this.connectionStatus = {
|
|
|
|
|
color: 'error',
|
|
|
|
|
icon: 'mdi-alert-circle',
|
2025-07-19 16:34:23 +03:30
|
|
|
|
text: 'خطا در بررسی وضعیت'
|
2025-07-18 06:29:39 +03:30
|
|
|
|
};
|
|
|
|
|
console.error('خطا در بررسی وضعیت:', error);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
updateConnectionStatus(status) {
|
|
|
|
|
const statusMap = {
|
|
|
|
|
'available': {
|
|
|
|
|
color: 'success',
|
|
|
|
|
icon: 'mdi-check-circle',
|
|
|
|
|
text: 'متصل'
|
|
|
|
|
},
|
|
|
|
|
'disabled': {
|
|
|
|
|
color: 'error',
|
|
|
|
|
icon: 'mdi-robot-off',
|
|
|
|
|
text: 'غیرفعال'
|
|
|
|
|
},
|
|
|
|
|
'no_api_key': {
|
|
|
|
|
color: 'warning',
|
|
|
|
|
icon: 'mdi-key-remove',
|
|
|
|
|
text: 'بدون کلید API'
|
2025-07-18 19:59:35 +03:30
|
|
|
|
}
|
2025-07-19 16:34:23 +03:30
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.connectionStatus = statusMap[status] || {
|
|
|
|
|
color: 'error',
|
|
|
|
|
icon: 'mdi-alert-circle',
|
|
|
|
|
text: 'خطا در اتصال'
|
|
|
|
|
};
|
2025-07-18 06:29:39 +03:30
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async loadBalance() {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get('/api/wizard/balance');
|
|
|
|
|
if (response.data.success) {
|
|
|
|
|
this.userBalance = response.data.balance;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
2025-07-18 06:29:39 +03:30
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در بارگذاری اعتبار:', error);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
2025-05-04 01:07:39 +03:30
|
|
|
|
},
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
// Conversations
|
|
|
|
|
async loadConversations() {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.post('/api/ai/conversations/list');
|
|
|
|
|
this.conversations = Array.isArray(response.data) ? response.data : [];
|
|
|
|
|
this.filteredConversations = [...this.conversations];
|
|
|
|
|
this.extractCategories();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در بارگذاری گفتگوها:', error);
|
|
|
|
|
this.conversations = [];
|
|
|
|
|
this.filteredConversations = [];
|
|
|
|
|
this.categories = [];
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
2025-05-04 01:07:39 +03:30
|
|
|
|
},
|
2025-07-18 06:29:39 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
extractCategories() {
|
|
|
|
|
const categorySet = new Set();
|
|
|
|
|
this.conversations.forEach(conv => {
|
|
|
|
|
if (conv.category) {
|
|
|
|
|
categorySet.add(conv.category);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
this.categories = Array.from(categorySet);
|
|
|
|
|
},
|
|
|
|
|
|
2025-07-18 06:29:39 +03:30
|
|
|
|
async loadConversation(conversation) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.post(`/api/ai/conversations/${conversation.id}/messages`);
|
|
|
|
|
this.currentConversation = conversation;
|
|
|
|
|
this.userMessages = [];
|
|
|
|
|
|
2025-07-18 19:59:35 +03:30
|
|
|
|
const messages = Array.isArray(response.data) ? response.data : [];
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.convertMessages(messages);
|
2025-07-18 06:29:39 +03:30
|
|
|
|
|
|
|
|
|
this.showConversationsDialog = false;
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.scrollToBottom();
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در بارگذاری گفتگو:', error);
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
},
|
2025-07-18 06:29:39 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
convertMessages(messages) {
|
|
|
|
|
messages.forEach(msg => {
|
|
|
|
|
if (msg.role === 'user') {
|
|
|
|
|
this.userMessages.push(msg.content);
|
|
|
|
|
} else if (msg.role === 'assistant') {
|
|
|
|
|
this.userMessages.push({
|
|
|
|
|
isAI: true,
|
|
|
|
|
text: msg.content,
|
|
|
|
|
usage: {
|
|
|
|
|
prompt_tokens: msg.inputTokens,
|
|
|
|
|
completion_tokens: msg.outputTokens
|
|
|
|
|
},
|
|
|
|
|
cost: {
|
|
|
|
|
total_cost: msg.totalCost
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async newConversation() {
|
|
|
|
|
this.currentConversation = null;
|
|
|
|
|
this.userMessages = [];
|
|
|
|
|
this.showConversationsDialog = false;
|
|
|
|
|
this.setWelcomeMessage();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
searchConversations() {
|
|
|
|
|
if (!this.searchTerm) {
|
|
|
|
|
this.filteredConversations = [...this.conversations];
|
|
|
|
|
} else {
|
|
|
|
|
this.filteredConversations = this.conversations.filter(conv =>
|
|
|
|
|
conv.title && conv.title.toLowerCase().includes(this.searchTerm.toLowerCase())
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
filterByCategory() {
|
|
|
|
|
if (!this.selectedCategory) {
|
|
|
|
|
this.filteredConversations = [...this.conversations];
|
|
|
|
|
} else {
|
|
|
|
|
this.filteredConversations = this.conversations.filter(conv =>
|
|
|
|
|
conv.category === this.selectedCategory
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2025-07-18 06:29:39 +03:30
|
|
|
|
deleteConversation(conversation) {
|
|
|
|
|
this.conversationToDelete = conversation;
|
|
|
|
|
this.showDeleteDialog = true;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
},
|
2025-07-18 06:29:39 +03:30
|
|
|
|
|
|
|
|
|
async confirmDeleteConversation() {
|
|
|
|
|
if (!this.conversationToDelete) return;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
this.isLoading = true;
|
|
|
|
|
const response = await axios.post(`/api/ai/conversations/${this.conversationToDelete.id}/delete`);
|
|
|
|
|
|
|
|
|
|
if (response.data.success) {
|
|
|
|
|
if (this.currentConversation && this.currentConversation.id === this.conversationToDelete.id) {
|
|
|
|
|
this.newConversation();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await this.loadConversations();
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.showSuccessMessage('گفتگو با موفقیت حذف شد');
|
2025-07-18 06:29:39 +03:30
|
|
|
|
} else {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.showErrorMessage(response.data.error || 'خطا در حذف گفتگو');
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در حذف گفتگو:', error);
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.showErrorMessage('خطا در حذف گفتگو');
|
2025-07-18 06:29:39 +03:30
|
|
|
|
} finally {
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
this.showDeleteDialog = false;
|
|
|
|
|
this.conversationToDelete = null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
// Messages
|
2025-07-18 06:29:39 +03:30
|
|
|
|
setWelcomeMessage() {
|
2025-07-18 07:15:33 +03:30
|
|
|
|
if (!this.aiSettings.aiEnabled) {
|
|
|
|
|
this.displayWelcome = 'سرویس هوش مصنوعی در حال حاضر غیرفعال است. لطفاً با مدیر سیستم تماس بگیرید تا این سرویس را فعال کند.';
|
|
|
|
|
} else {
|
|
|
|
|
this.displayWelcome = 'سلام! من دستیار هوشمند حسابیکس هستم. چطور میتوانم به شما کمک کنم؟';
|
|
|
|
|
}
|
2025-07-18 06:29:39 +03:30
|
|
|
|
},
|
|
|
|
|
|
2025-05-04 01:07:39 +03:30
|
|
|
|
async sendMessage() {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
if (!this.userMessage.trim() || this.isLoading) return;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
|
2025-07-18 07:15:33 +03:30
|
|
|
|
if (!this.aiSettings.aiEnabled) {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.addErrorMessage('سرویس هوش مصنوعی در حال حاضر غیرفعال است. لطفاً با مدیر سیستم تماس بگیرید تا این سرویس را فعال کند.');
|
2025-07-18 07:15:33 +03:30
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 06:29:39 +03:30
|
|
|
|
if (this.userBalance < 100) {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.addErrorMessage(
|
|
|
|
|
`اعتبار شما کافی نیست (${this.formatBalance(this.userBalance)}). برای شارژ حساب خود روی دکمه زیر کلیک کنید:`,
|
|
|
|
|
true
|
|
|
|
|
);
|
2025-07-18 06:29:39 +03:30
|
|
|
|
return;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 06:29:39 +03:30
|
|
|
|
const message = this.userMessage;
|
|
|
|
|
this.userMessage = '';
|
|
|
|
|
this.userMessages.push(message);
|
|
|
|
|
this.isLoading = true;
|
|
|
|
|
this.isTyping = true;
|
|
|
|
|
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.scrollToBottom();
|
|
|
|
|
});
|
2025-05-04 01:07:39 +03:30
|
|
|
|
|
2025-07-18 02:30:04 +03:30
|
|
|
|
try {
|
2025-07-18 19:59:35 +03:30
|
|
|
|
const personKeywords = ['شخص', 'مشتری', 'تامینکننده', 'کارمند', 'موجودی', 'تراکنش'];
|
|
|
|
|
const isPersonRequest = personKeywords.some(keyword =>
|
|
|
|
|
message.toLowerCase().includes(keyword.toLowerCase())
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (isPersonRequest) {
|
|
|
|
|
await this.showPersonDetails(message);
|
|
|
|
|
}
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
const response = await axios.post('/api/wizard/talk', {
|
2025-07-18 02:30:04 +03:30
|
|
|
|
message: message,
|
2025-07-18 06:29:39 +03:30
|
|
|
|
conversationId: this.currentConversation?.id || null
|
|
|
|
|
});
|
2025-05-04 01:07:39 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.handleAIResponse(response);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
} catch (error) {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
console.error('خطا در ارسال پیام:', error);
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.addErrorMessage('خطا در ارتباط با سرور');
|
2025-07-18 06:29:39 +03:30
|
|
|
|
} finally {
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
this.isTyping = false;
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.scrollToBottom();
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.focusInput();
|
2025-07-18 06:29:39 +03:30
|
|
|
|
});
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
2025-07-18 06:29:39 +03:30
|
|
|
|
},
|
2025-05-04 01:07:39 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
handleAIResponse(response) {
|
|
|
|
|
if (response && response.data && response.data.success) {
|
|
|
|
|
this.userMessages.push({
|
|
|
|
|
isAI: true,
|
|
|
|
|
text: response.data.response,
|
|
|
|
|
usage: response.data.usage,
|
|
|
|
|
cost: response.data.cost,
|
|
|
|
|
debug_info: response.data.debug_info ? {
|
|
|
|
|
...response.data.debug_info,
|
|
|
|
|
expanded: false
|
|
|
|
|
} : null
|
|
|
|
|
});
|
|
|
|
|
this.loadBalance();
|
|
|
|
|
this.loadConversations();
|
|
|
|
|
this.showSuccessMessage('پاسخ دریافت شد');
|
|
|
|
|
} else if (response && response.data) {
|
|
|
|
|
this.userMessages.push({
|
|
|
|
|
isAI: true,
|
|
|
|
|
text: `خطا: ${response.data.error}`,
|
|
|
|
|
isError: true,
|
|
|
|
|
debug_info: response.data.debug_info || null
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.userMessages.push({
|
|
|
|
|
isAI: true,
|
|
|
|
|
text: 'خطا در ارتباط با سرور',
|
|
|
|
|
isError: true,
|
|
|
|
|
debug_info: null
|
|
|
|
|
});
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
2025-07-18 02:30:04 +03:30
|
|
|
|
},
|
2025-07-18 06:29:39 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
addErrorMessage(message, showChargeButton = false) {
|
|
|
|
|
this.userMessages.push({
|
|
|
|
|
isAI: true,
|
|
|
|
|
text: message,
|
|
|
|
|
isError: true,
|
|
|
|
|
showChargeButton
|
|
|
|
|
});
|
|
|
|
|
this.userMessage = '';
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.scrollToBottom();
|
2025-07-18 06:29:39 +03:30
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
useSuggestion(suggestion) {
|
|
|
|
|
this.userMessage = suggestion;
|
2025-07-18 19:59:35 +03:30
|
|
|
|
},
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
// Person Management
|
2025-07-18 19:59:35 +03:30
|
|
|
|
async searchPersons(searchTerm) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.post('/api/wizard/persons/search', {
|
|
|
|
|
search: searchTerm
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (response.data.success) {
|
|
|
|
|
return response.data.persons;
|
|
|
|
|
} else {
|
|
|
|
|
console.error('خطا در جستجوی اشخاص:', response.data.error);
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در جستجوی اشخاص:', error);
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async getPersonDetails(personId) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(`/api/wizard/persons/${personId}`);
|
|
|
|
|
|
|
|
|
|
if (response.data.success) {
|
|
|
|
|
return response.data.person;
|
|
|
|
|
} else {
|
|
|
|
|
console.error('خطا در دریافت اطلاعات شخص:', response.data.error);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در دریافت اطلاعات شخص:', error);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async getPersonTransactions(personId, limit = 10) {
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(`/api/wizard/persons/${personId}/transactions?limit=${limit}`);
|
|
|
|
|
|
|
|
|
|
if (response.data.success) {
|
|
|
|
|
return response.data.transactions;
|
|
|
|
|
} else {
|
|
|
|
|
console.error('خطا در دریافت تراکنشهای شخص:', response.data.error);
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در دریافت تراکنشهای شخص:', error);
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async showPersonDetails(searchTerm) {
|
|
|
|
|
try {
|
|
|
|
|
const persons = await this.searchPersons(searchTerm);
|
|
|
|
|
|
|
|
|
|
if (persons.length === 0) {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.showWarningMessage('شخصی با این نام یافت نشد');
|
2025-07-18 19:59:35 +03:30
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const person = persons[0];
|
|
|
|
|
const personDetails = await this.getPersonDetails(person.id);
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
2025-07-18 19:59:35 +03:30
|
|
|
|
if (!personDetails) {
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.showErrorMessage('خطا در دریافت اطلاعات شخص');
|
2025-07-18 19:59:35 +03:30
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const transactions = await this.getPersonTransactions(person.id, 10);
|
|
|
|
|
|
|
|
|
|
this.selectedPerson = personDetails;
|
|
|
|
|
this.personTransactions = transactions;
|
|
|
|
|
this.showPersonInfo = true;
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('خطا در نمایش اطلاعات شخص:', error);
|
2025-07-19 16:34:23 +03:30
|
|
|
|
this.showErrorMessage('خطا در نمایش اطلاعات شخص');
|
2025-07-18 19:59:35 +03:30
|
|
|
|
}
|
2025-07-19 13:49:33 +03:30
|
|
|
|
},
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
// Debug
|
|
|
|
|
toggleJsonView(key) {
|
|
|
|
|
this.expandedJsonViews[key] = !this.expandedJsonViews[key];
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
openDebugDialog(debugInfo, messageIndex) {
|
|
|
|
|
this.currentDebugInfo = debugInfo;
|
|
|
|
|
this.showDebugDialog = true;
|
|
|
|
|
this.expandedJsonViews = {};
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getDebugInfoCount(debugInfo) {
|
|
|
|
|
let count = 0;
|
|
|
|
|
if (debugInfo.operation_type) count++;
|
|
|
|
|
if (debugInfo.current_step) count++;
|
|
|
|
|
if (debugInfo.attempt_count) count++;
|
|
|
|
|
if (debugInfo.next_action) count++;
|
|
|
|
|
if (debugInfo.final_result) count++;
|
|
|
|
|
if (debugInfo.final_data) count++;
|
|
|
|
|
if (debugInfo.json_response) count++;
|
|
|
|
|
if (debugInfo.tool_commands && debugInfo.tool_commands.length > 0) count++;
|
|
|
|
|
if (debugInfo.execution_result) count++;
|
|
|
|
|
if (debugInfo.execution_results && debugInfo.execution_results.length > 0) count++;
|
|
|
|
|
if (debugInfo.ai_response) count++;
|
|
|
|
|
if (debugInfo.error) count++;
|
|
|
|
|
return count;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getOperationTypeColor(operationType) {
|
|
|
|
|
const colorMap = {
|
|
|
|
|
'add_person': 'success',
|
|
|
|
|
'edit_person': 'info',
|
|
|
|
|
'delete_person': 'error',
|
|
|
|
|
'search_person': 'primary',
|
|
|
|
|
'show_person': 'primary',
|
|
|
|
|
'add_phone': 'success',
|
|
|
|
|
'remove_phone': 'error',
|
|
|
|
|
'update_balance': 'warning',
|
|
|
|
|
'show_transactions': 'info',
|
|
|
|
|
'default': 'primary'
|
|
|
|
|
};
|
|
|
|
|
return colorMap[operationType] || colorMap.default;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getOperationTypeText(operationType) {
|
|
|
|
|
const textMap = {
|
|
|
|
|
'add_person': 'افزودن شخص',
|
|
|
|
|
'edit_person': 'ویرایش شخص',
|
|
|
|
|
'delete_person': 'حذف شخص',
|
|
|
|
|
'search_person': 'جستجوی شخص',
|
|
|
|
|
'show_person': 'نمایش شخص',
|
|
|
|
|
'add_phone': 'افزودن شماره تلفن',
|
|
|
|
|
'remove_phone': 'حذف شماره تلفن',
|
|
|
|
|
'update_balance': 'بهروزرسانی موجودی',
|
|
|
|
|
'show_transactions': 'نمایش تراکنشها',
|
|
|
|
|
'default': 'عملیات نامشخص'
|
|
|
|
|
};
|
|
|
|
|
return textMap[operationType] || textMap.default;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Utilities
|
|
|
|
|
formatBalance(balance) {
|
|
|
|
|
const intBalance = Math.round(balance);
|
|
|
|
|
if (intBalance < 1000) {
|
|
|
|
|
return `${intBalance.toLocaleString('fa-IR')} ریال`;
|
|
|
|
|
} else {
|
|
|
|
|
return `${(intBalance / 1000).toFixed(1)} هزار ریال`;
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
2025-07-19 16:34:23 +03:30
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
formatTime(date) {
|
|
|
|
|
return date.toLocaleTimeString('fa-IR', {
|
|
|
|
|
hour: '2-digit',
|
|
|
|
|
minute: '2-digit'
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
renderMarkdown(text) {
|
|
|
|
|
if (!text) return '';
|
|
|
|
|
const html = marked(text);
|
|
|
|
|
return DOMPurify.sanitize(html);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
scrollToBottom() {
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
if (this.$refs.messagesContainer) {
|
|
|
|
|
this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
focusInput() {
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
if (this.$refs.messageInput) {
|
|
|
|
|
this.$refs.messageInput.focus();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
goToChargePage() {
|
|
|
|
|
this.$router.push('/acc/sms/panel');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Notifications
|
|
|
|
|
showSuccessMessage(text) {
|
|
|
|
|
this.$emit('show-snackbar', {
|
|
|
|
|
text,
|
|
|
|
|
color: 'success'
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
showErrorMessage(text) {
|
|
|
|
|
this.$emit('show-snackbar', {
|
|
|
|
|
text,
|
|
|
|
|
color: 'error'
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
showWarningMessage(text) {
|
|
|
|
|
this.$emit('show-snackbar', {
|
|
|
|
|
text,
|
|
|
|
|
color: 'warning'
|
|
|
|
|
});
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
2025-07-18 06:29:39 +03:30
|
|
|
|
};
|
2025-04-12 18:50:34 +03:30
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
2025-07-19 16:34:23 +03:30
|
|
|
|
/* Main Layout */
|
|
|
|
|
.main-container {
|
|
|
|
|
height: calc(100vh - 70px);
|
2025-05-04 01:07:39 +03:30
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
|
|
|
overflow: hidden;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
/* Header Styles */
|
|
|
|
|
.ai-header {
|
|
|
|
|
background: linear-gradient(135deg, #1a237e 0%, #3949ab 100%) !important;
|
|
|
|
|
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1);
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.header-content {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
width: 100%;
|
|
|
|
|
max-width: 1400px;
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
padding: 0 24px;
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.header-left {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 16px;
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.logo-container {
|
|
|
|
|
background: rgba(255, 255, 255, 0.2);
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 8px;
|
|
|
|
|
backdrop-filter: blur(10px);
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.title-section {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.app-title {
|
|
|
|
|
font-size: 1.25rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: white;
|
|
|
|
|
margin: 0;
|
|
|
|
|
line-height: 1.2;
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.app-subtitle {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
color: rgba(255, 255, 255, 0.8);
|
|
|
|
|
margin: 0;
|
|
|
|
|
line-height: 1.2;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.header-center {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
flex: 1;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
display: flex;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
justify-content: center;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.status-indicators {
|
2025-05-04 01:07:39 +03:30
|
|
|
|
display: flex;
|
|
|
|
|
gap: 16px;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
align-items: center;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.status-item {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: all 0.3s ease;
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.status-chip {
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
font-weight: 500;
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.status-chip:hover {
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.header-right {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.action-btn {
|
|
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
transition: all 0.3s ease;
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.action-btn:hover {
|
|
|
|
|
background: rgba(255, 255, 255, 0.2);
|
|
|
|
|
transform: scale(1.1);
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
/* Info Section */
|
|
|
|
|
.info-section {
|
|
|
|
|
padding: 12px 24px 0;
|
|
|
|
|
flex-shrink: 0;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.info-cards {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
display: flex;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
gap: 12px;
|
|
|
|
|
max-width: 1400px;
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-card {
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: hidden;
|
2025-07-18 06:29:39 +03:30
|
|
|
|
background: white;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
flex: 1;
|
|
|
|
|
min-width: 200px;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.info-card:hover {
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
2025-07-19 16:34:23 +03:30
|
|
|
|
|
|
|
|
|
.card-content {
|
|
|
|
|
padding: 12px 16px;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.pricing-row,
|
|
|
|
|
.stats-row {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 8px;
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.pricing-icon,
|
|
|
|
|
.stats-icon {
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-info,
|
|
|
|
|
.stats-info {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 2px;
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-label,
|
|
|
|
|
.stats-label {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
font-size: 0.75rem;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
color: #666;
|
|
|
|
|
font-weight: 500;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.pricing-value,
|
|
|
|
|
.stats-value {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
line-height: 1.3;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.pricing-unit {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
color: #999;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
/* Chat Section */
|
|
|
|
|
.chat-section {
|
|
|
|
|
flex: 1;
|
|
|
|
|
padding: 20px 24px;
|
|
|
|
|
overflow: hidden;
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.chat-container {
|
|
|
|
|
height: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
background: white;
|
|
|
|
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
2025-07-18 06:29:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.chat-header {
|
|
|
|
|
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
|
|
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
padding: 16px 24px;
|
|
|
|
|
flex-shrink: 0;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.conversation-info {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
2025-05-04 01:07:39 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.conversation-title {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
2025-05-04 01:07:39 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.title-text {
|
|
|
|
|
font-size: 1.125rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.category-chip {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
font-weight: 500;
|
2025-04-12 18:50:34 +03:30
|
|
|
|
}
|
2025-07-18 02:30:04 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.new-chat-btn {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
transition: all 0.3s ease;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.new-chat-btn:hover {
|
|
|
|
|
background: rgba(26, 35, 126, 0.1);
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Messages Area */
|
|
|
|
|
.messages-area {
|
|
|
|
|
flex: 1;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.messages-container {
|
|
|
|
|
flex: 1;
|
2025-07-18 06:29:39 +03:30
|
|
|
|
overflow-y: auto;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
padding: 24px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 20px;
|
|
|
|
|
scroll-behavior: smooth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
max-width: 80%;
|
|
|
|
|
animation: messageSlideIn 0.3s ease-out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.user-message {
|
|
|
|
|
align-self: flex-end;
|
|
|
|
|
flex-direction: row-reverse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ai-message {
|
|
|
|
|
align-self: flex-start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-avatar {
|
|
|
|
|
flex-shrink: 0;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.message-content {
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
border-top-left-radius: 4px;
|
|
|
|
|
position: relative;
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.user-message .message-content {
|
|
|
|
|
background: linear-gradient(135deg, #1a237e 0%, #3949ab 100%);
|
|
|
|
|
color: white;
|
|
|
|
|
border-top-left-radius: 20px;
|
|
|
|
|
border-top-right-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-content:hover {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
transform: translateY(-1px);
|
2025-07-19 16:34:23 +03:30
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.message-text {
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-time {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
margin-top: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.error-message {
|
|
|
|
|
background: #ffebee !important;
|
|
|
|
|
border: 1px solid #ffcdd2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.success-message {
|
|
|
|
|
background: #f1f8e9 !important;
|
|
|
|
|
border: 1px solid #c8e6c9;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Debug Section */
|
|
|
|
|
.debug-section {
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-btn {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
font-weight: 500;
|
2025-07-18 06:29:39 +03:30
|
|
|
|
border-radius: 8px;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
transition: all 0.3s ease;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.debug-btn:hover {
|
2025-07-18 06:29:39 +03:30
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.debug-count {
|
|
|
|
|
margin-right: 4px;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
/* Charge Section */
|
|
|
|
|
.charge-section {
|
|
|
|
|
margin-top: 12px;
|
2025-07-18 06:29:39 +03:30
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 06:29:39 +03:30
|
|
|
|
.charge-btn {
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
font-weight: 500;
|
2025-07-19 16:34:23 +03:30
|
|
|
|
transition: all 0.3s ease;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 06:29:39 +03:30
|
|
|
|
.charge-btn:hover {
|
2025-07-18 02:30:04 +03:30
|
|
|
|
transform: translateY(-1px);
|
2025-07-18 06:29:39 +03:30
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
/* Suggestions */
|
|
|
|
|
.suggestions-section {
|
|
|
|
|
padding: 24px;
|
|
|
|
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
|
|
|
|
flex-shrink: 0;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.suggestions-title {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.suggestions-grid {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 8px;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.suggestion-chip {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
border-radius: 16px;
|
2025-07-18 02:30:04 +03:30
|
|
|
|
}
|
2025-07-19 13:49:33 +03:30
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.suggestion-chip:hover {
|
|
|
|
|
transform: translateY(-2px);
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
/* Input Section */
|
|
|
|
|
.input-section {
|
|
|
|
|
padding: 20px 24px;
|
|
|
|
|
background: white;
|
|
|
|
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
flex-shrink: 0;
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.input-container {
|
|
|
|
|
max-width: 1400px;
|
|
|
|
|
margin: 0 auto;
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.message-input {
|
|
|
|
|
border-radius: 24px;
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
transition: all 0.3s ease;
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.message-input:hover {
|
|
|
|
|
background: #f1f3f4;
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.message-input:focus-within {
|
|
|
|
|
background: white;
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.send-btn {
|
|
|
|
|
transition: all 0.3s ease;
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.send-btn:hover {
|
|
|
|
|
transform: scale(1.1);
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.send-icon {
|
|
|
|
|
transform: rotate(180deg);
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
/* Typing Indicator */
|
|
|
|
|
.typing-indicator {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
gap: 4px;
|
|
|
|
|
padding: 8px 0;
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.typing-indicator span {
|
|
|
|
|
width: 8px;
|
|
|
|
|
height: 8px;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
background: #666;
|
|
|
|
|
animation: typing 1.4s infinite ease-in-out;
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
|
|
|
|
|
2025-07-19 16:34:23 +03:30
|
|
|
|
.typing-indicator span:nth-child(1) { animation-delay: -0.32s; }
|
|
|
|
|
.typing-indicator span:nth-child(2) { animation-delay: -0.16s; }
|
|
|
|
|
|
|
|
|
|
@keyframes typing {
|
|
|
|
|
0%, 80%, 100% {
|
|
|
|
|
transform: scale(0.8);
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
}
|
|
|
|
|
40% {
|
|
|
|
|
transform: scale(1);
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes messageSlideIn {
|
|
|
|
|
from {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(20px);
|
|
|
|
|
}
|
|
|
|
|
to {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Dialog Styles */
|
|
|
|
|
.conversations-dialog,
|
|
|
|
|
.delete-dialog,
|
|
|
|
|
.person-dialog {
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dialog-header {
|
|
|
|
|
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
|
|
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
padding: 20px 24px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dialog-title {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
font-size: 1.125rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dialog-content {
|
|
|
|
|
padding: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Filters */
|
|
|
|
|
.filters-section {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
|
|
gap: 16px;
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-field,
|
|
|
|
|
.category-field {
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Conversations List */
|
|
|
|
|
.conversations-list {
|
|
|
|
|
max-height: 400px;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversations-items {
|
|
|
|
|
background: transparent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-item {
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-item:hover {
|
|
|
|
|
background: rgba(26, 35, 126, 0.1);
|
|
|
|
|
transform: translateX(4px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-title {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-details {
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-meta {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-date {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
color: #999;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-stats {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.delete-btn {
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.delete-btn:hover {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: scale(1.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-item:hover .delete-btn {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dialog-actions {
|
|
|
|
|
padding: 16px 24px;
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Delete Dialog */
|
|
|
|
|
.delete-header {
|
|
|
|
|
background: linear-gradient(135deg, #ffebee 0%, #ffffff 100%);
|
|
|
|
|
color: #d32f2f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.delete-content {
|
|
|
|
|
padding: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.delete-message {
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
color: #333;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.delete-warning {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
color: #666;
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.delete-actions {
|
|
|
|
|
padding: 16px 24px;
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Debug Dialog */
|
|
|
|
|
.debug-dialog {
|
|
|
|
|
height: 100vh;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-header {
|
|
|
|
|
background: linear-gradient(135deg, #1a237e 0%, #3949ab 100%);
|
|
|
|
|
color: white;
|
|
|
|
|
padding: 20px 24px;
|
|
|
|
|
position: sticky;
|
|
|
|
|
top: 0;
|
|
|
|
|
z-index: 10;
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-title-section {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-icon {
|
|
|
|
|
background: rgba(255, 255, 255, 0.2);
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 12px;
|
|
|
|
|
backdrop-filter: blur(10px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-info {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-title {
|
|
|
|
|
font-size: 1.5rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
margin: 0;
|
|
|
|
|
color: white;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-subtitle {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
margin: 4px 0 0 0;
|
|
|
|
|
opacity: 0.8;
|
|
|
|
|
color: rgba(255, 255, 255, 0.9);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-count {
|
|
|
|
|
margin-right: 16px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.close-btn {
|
|
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.close-btn:hover {
|
|
|
|
|
background: rgba(255, 255, 255, 0.2);
|
|
|
|
|
transform: scale(1.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-content {
|
|
|
|
|
flex: 1;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
padding: 24px;
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Debug Main Cards */
|
|
|
|
|
.debug-main-cards {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
|
|
|
gap: 20px;
|
|
|
|
|
margin-bottom: 32px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-main-card {
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
border: none;
|
|
|
|
|
background: white;
|
|
|
|
|
animation: slideInUp 0.4s ease-out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-main-card:hover {
|
|
|
|
|
transform: translateY(-4px);
|
|
|
|
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-main-card:nth-child(1) { animation-delay: 0.1s; }
|
|
|
|
|
.debug-main-card:nth-child(2) { animation-delay: 0.2s; }
|
|
|
|
|
.debug-main-card:nth-child(3) { animation-delay: 0.3s; }
|
|
|
|
|
.debug-main-card:nth-child(4) { animation-delay: 0.4s; }
|
|
|
|
|
|
|
|
|
|
.card-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
gap: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-icon {
|
|
|
|
|
background: linear-gradient(135deg, #1a237e 0%, #3949ab 100%);
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 12px;
|
|
|
|
|
min-width: 48px;
|
|
|
|
|
height: 48px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-content {
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-title {
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
margin: 0 0 8px 0;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-text {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
color: #666;
|
|
|
|
|
margin: 0;
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.operation-chip {
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.attempt-progress {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.progress-bar {
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.attempt-text {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
color: #666;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Debug Results Section */
|
|
|
|
|
.debug-results-section {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-section-card {
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
background: white;
|
|
|
|
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
animation: slideInUp 0.4s ease-out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-section-card:hover {
|
|
|
|
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
|
|
|
|
border-color: rgba(0, 0, 0, 0.15);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
|
|
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-content {
|
|
|
|
|
padding: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Tools Grid */
|
|
|
|
|
.tools-grid {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-item {
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
border-left: 4px solid #1a237e;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-item:hover {
|
|
|
|
|
background: #e3f2fd;
|
|
|
|
|
transform: translateX(4px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-name {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.view-btn {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.view-btn:hover {
|
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Timeline */
|
|
|
|
|
.execution-timeline {
|
|
|
|
|
position: relative;
|
|
|
|
|
padding-left: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.execution-timeline::before {
|
|
|
|
|
content: '';
|
|
|
|
|
position: absolute;
|
|
|
|
|
left: 8px;
|
|
|
|
|
top: 0;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
width: 2px;
|
|
|
|
|
background: linear-gradient(to bottom, #4caf50, #81c784);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.timeline-item {
|
|
|
|
|
position: relative;
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.timeline-marker {
|
|
|
|
|
position: absolute;
|
|
|
|
|
left: -16px;
|
|
|
|
|
top: 0;
|
|
|
|
|
background: white;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
width: 16px;
|
|
|
|
|
height: 16px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.timeline-content {
|
|
|
|
|
background: #f1f8e9;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
border-left: 4px solid #4caf50;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.timeline-content:hover {
|
|
|
|
|
background: #e8f5e8;
|
|
|
|
|
transform: translateX(4px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.timeline-header {
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.timeline-title {
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.timeline-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* JSON Container */
|
|
|
|
|
.json-container {
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
border: 1px solid #e0e0e0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.json-content {
|
|
|
|
|
font-family: 'Fira Code', 'Courier New', monospace;
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
color: #333;
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
margin: 0;
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
border: 1px solid #e0e0e0;
|
|
|
|
|
max-height: 300px;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* AI Response Container */
|
|
|
|
|
.ai-response-container {
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
background: #e3f2fd;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
border-left: 4px solid #2196f3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ai-response-content {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
color: #333;
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Success and Error Cards */
|
|
|
|
|
.success-card {
|
|
|
|
|
border-left: 4px solid #4caf50;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.error-card {
|
|
|
|
|
border-left: 4px solid #f44336;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.final-result-content {
|
|
|
|
|
background: #e8f5e8;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
border-left: 4px solid #4caf50;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.result-text {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
color: #2e7d32;
|
|
|
|
|
margin: 0;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.error-content {
|
|
|
|
|
background: #ffebee;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
padding: 16px;
|
|
|
|
|
border-left: 4px solid #f44336;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.error-text {
|
|
|
|
|
font-size: 0.875rem;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
color: #d32f2f;
|
|
|
|
|
margin: 0;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Animations */
|
|
|
|
|
@keyframes slideInUp {
|
|
|
|
|
from {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(30px);
|
|
|
|
|
}
|
|
|
|
|
to {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Responsive Design */
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
.header-content {
|
|
|
|
|
padding: 0 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-title {
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-subtitle {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.status-indicators {
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.status-chip {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-center {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-right {
|
|
|
|
|
margin-right: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-section {
|
|
|
|
|
padding: 6px 12px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-cards {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-card {
|
|
|
|
|
min-width: auto;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-content {
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-row,
|
|
|
|
|
.stats-row {
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-icon,
|
|
|
|
|
.stats-icon {
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-label,
|
|
|
|
|
.stats-label {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-value,
|
|
|
|
|
.stats-value {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
line-height: 1.2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-unit {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-section {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-container {
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-header {
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-title {
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title-text {
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.messages-container {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
gap: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message {
|
|
|
|
|
max-width: 92%;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-content {
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-text {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-time {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestions-section {
|
|
|
|
|
padding: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestions-title {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestions-grid {
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestion-chip {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
height: 28px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.input-section {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-input {
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.filters-section {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-field,
|
|
|
|
|
.category-field {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversations-list {
|
|
|
|
|
max-height: 350px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-item {
|
|
|
|
|
padding: 8px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-title {
|
|
|
|
|
font-size: 0.85rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-stats {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-header {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-title {
|
|
|
|
|
font-size: 1.1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-subtitle {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-main-cards {
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-header {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-icon {
|
|
|
|
|
min-width: 40px;
|
|
|
|
|
height: 40px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-title {
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-text {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-content {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-item,
|
|
|
|
|
.timeline-content {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-name,
|
|
|
|
|
.timeline-title {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.view-btn {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.json-content {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
padding: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-content {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
.header-left {
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.logo-container {
|
|
|
|
|
padding: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-title {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-subtitle {
|
|
|
|
|
font-size: 0.6rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.status-indicators {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-section {
|
|
|
|
|
padding: 4px 8px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info-cards {
|
|
|
|
|
gap: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-content {
|
|
|
|
|
padding: 6px 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-row,
|
|
|
|
|
.stats-row {
|
|
|
|
|
gap: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-icon,
|
|
|
|
|
.stats-icon {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-label,
|
|
|
|
|
.stats-label {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-value,
|
|
|
|
|
.stats-value {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pricing-unit {
|
|
|
|
|
font-size: 0.6rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-section {
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-header {
|
|
|
|
|
padding: 10px 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title-text {
|
|
|
|
|
font-size: 0.9rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.messages-container {
|
|
|
|
|
padding: 8px;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message {
|
|
|
|
|
max-width: 95%;
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-content {
|
|
|
|
|
padding: 10px 14px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-text {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-time {
|
|
|
|
|
font-size: 0.6rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestions-section {
|
|
|
|
|
padding: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestions-title {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestions-grid {
|
|
|
|
|
gap: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestion-chip {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
height: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.input-section {
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-input {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.filters-section {
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.search-field,
|
|
|
|
|
.category-field {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversations-list {
|
|
|
|
|
max-height: 300px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-item {
|
|
|
|
|
padding: 6px 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-title {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.conversation-stats {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-header {
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-title {
|
|
|
|
|
font-size: 1rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-subtitle {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-main-cards {
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-header {
|
|
|
|
|
padding: 8px;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-icon {
|
|
|
|
|
min-width: 36px;
|
|
|
|
|
height: 36px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-title {
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-text {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-content {
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
padding: 10px 12px;
|
|
|
|
|
font-size: 0.8rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-item,
|
|
|
|
|
.timeline-content {
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tool-name,
|
|
|
|
|
.timeline-title {
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.view-btn {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.json-content {
|
|
|
|
|
font-size: 0.6rem;
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.debug-content {
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 480px) {
|
|
|
|
|
.header-content {
|
|
|
|
|
padding: 0 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-left {
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.logo-container {
|
|
|
|
|
padding: 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-title {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-subtitle {
|
|
|
|
|
font-size: 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.status-indicators {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-center {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-right {
|
|
|
|
|
margin-right: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-btn {
|
|
|
|
|
width: 36px;
|
|
|
|
|
height: 36px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message {
|
|
|
|
|
max-width: 95%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message-content {
|
|
|
|
|
padding: 12px 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestions-grid {
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.suggestion-chip {
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 360px) {
|
|
|
|
|
.header-content {
|
|
|
|
|
padding: 0 4px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-left {
|
|
|
|
|
gap: 6px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.logo-container {
|
|
|
|
|
padding: 3px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-title {
|
|
|
|
|
font-size: 0.65rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.app-subtitle {
|
|
|
|
|
font-size: 0.45rem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-btn {
|
|
|
|
|
width: 32px;
|
|
|
|
|
height: 32px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-btn .v-icon {
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
}
|
2025-07-19 13:49:33 +03:30
|
|
|
|
}
|
2025-04-12 18:50:34 +03:30
|
|
|
|
</style>
|