фикс счетчиков
This commit is contained in:
parent
d4c869a82c
commit
a14997b84c
25
src/App.vue
25
src/App.vue
@ -39,10 +39,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useAuth } from '@/auth';
|
import { useAuth } from '@/auth';
|
||||||
import { ref, watch, onMounted, computed, onUnmounted } from 'vue';
|
import { ref, watch, onMounted, computed, onUnmounted } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import api from '@/services/api';
|
import api from '@/services/api';
|
||||||
import { getSocket, connectSocket } from '@/services/socketService';
|
import { getSocket, connectSocket } from '@/services/socketService';
|
||||||
|
|
||||||
const { user, isAuthenticated, logout, fetchUser } = useAuth();
|
const { user, isAuthenticated, logout, fetchUser } = useAuth();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
// Используем локальные переменные для отслеживания состояния
|
// Используем локальные переменные для отслеживания состояния
|
||||||
const userData = ref(null);
|
const userData = ref(null);
|
||||||
@ -83,15 +85,26 @@ const handleNewMessage = (message) => {
|
|||||||
|
|
||||||
// Обработчик прочитанных сообщений
|
// Обработчик прочитанных сообщений
|
||||||
const handleMessagesRead = ({ conversationId, readerId }) => {
|
const handleMessagesRead = ({ conversationId, readerId }) => {
|
||||||
|
console.log('[App] Получено событие messagesRead:', { conversationId, readerId, currentUserId: user.value?._id });
|
||||||
|
|
||||||
// Если текущий пользователь прочитал сообщения
|
// Если текущий пользователь прочитал сообщения
|
||||||
if (readerId === user.value?._id) {
|
if (readerId === user.value?._id) {
|
||||||
const conversation = conversations.value.find(c => c._id === conversationId);
|
const conversation = conversations.value.find(c => c._id === conversationId);
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
|
console.log('[App] Сбрасываем счетчик для диалога:', conversationId);
|
||||||
conversation.unreadCount = 0;
|
conversation.unreadCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Дополнительный обработчик для синхронизации при переходе в чат
|
||||||
|
const handleRouteChange = () => {
|
||||||
|
// Обновляем данные диалогов при изменении маршрута
|
||||||
|
if (isAuthenticated.value) {
|
||||||
|
fetchConversations();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Обновляем локальные переменные при изменении состояния аутентификации
|
// Обновляем локальные переменные при изменении состояния аутентификации
|
||||||
watch(() => isAuthenticated.value, (newVal) => {
|
watch(() => isAuthenticated.value, (newVal) => {
|
||||||
console.log('[App] isAuthenticated изменился:', newVal);
|
console.log('[App] isAuthenticated изменился:', newVal);
|
||||||
@ -109,6 +122,18 @@ watch(() => user.value, (newVal) => {
|
|||||||
userData.value = newVal;
|
userData.value = newVal;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Следим за изменением маршрута для обновления счетчика
|
||||||
|
watch(() => route.path, (newPath, oldPath) => {
|
||||||
|
console.log('[App] Маршрут изменился:', { from: oldPath, to: newPath });
|
||||||
|
|
||||||
|
// Если переходим в чат или возвращаемся из чата, обновляем счетчики
|
||||||
|
if (newPath.startsWith('/chat/') || oldPath?.startsWith('/chat/')) {
|
||||||
|
setTimeout(() => {
|
||||||
|
fetchConversations();
|
||||||
|
}, 500); // Небольшая задержка для завершения операций чтения
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Настройка сокет-соединения
|
// Настройка сокет-соединения
|
||||||
const setupSocketConnection = () => {
|
const setupSocketConnection = () => {
|
||||||
socket = getSocket();
|
socket = getSocket();
|
||||||
|
@ -46,12 +46,6 @@
|
|||||||
<div v-else class="user-photo-placeholder">
|
<div v-else class="user-photo-placeholder">
|
||||||
<i class="bi-person"></i>
|
<i class="bi-person"></i>
|
||||||
</div>
|
</div>
|
||||||
<span
|
|
||||||
v-if="conversation.unreadCount > 0"
|
|
||||||
class="unread-badge"
|
|
||||||
>
|
|
||||||
{{ conversation.unreadCount < 100 ? conversation.unreadCount : '99+' }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Conversation Info -->
|
<!-- Conversation Info -->
|
||||||
@ -74,8 +68,18 @@
|
|||||||
</template>
|
</template>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="conversation-arrow">
|
|
||||||
<i class="bi-chevron-right"></i>
|
<!-- Right side: Unread badge and arrow -->
|
||||||
|
<div class="conversation-right">
|
||||||
|
<span
|
||||||
|
v-if="conversation.unreadCount > 0"
|
||||||
|
class="unread-badge"
|
||||||
|
>
|
||||||
|
{{ conversation.unreadCount < 100 ? conversation.unreadCount : '99+' }}
|
||||||
|
</span>
|
||||||
|
<div class="conversation-arrow">
|
||||||
|
<i class="bi-chevron-right"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
@ -505,28 +509,82 @@ const getDialogsCountText = (count) => {
|
|||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Индикатор непрочитанных сообщений */
|
/* Правая часть диалога с счетчиком и стрелкой */
|
||||||
.unread-badge {
|
.conversation-right {
|
||||||
position: absolute;
|
display: flex;
|
||||||
top: -2px;
|
flex-direction: column;
|
||||||
right: -2px;
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Индикатор непрочитанных сообщений - теперь в правой части */
|
||||||
|
.conversation-right .unread-badge {
|
||||||
|
position: static;
|
||||||
background: linear-gradient(135deg, #ff6b6b, #ff5252);
|
background: linear-gradient(135deg, #ff6b6b, #ff5252);
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
border-radius: 10px;
|
border-radius: 12px;
|
||||||
min-width: 20px;
|
min-width: 22px;
|
||||||
height: 20px;
|
height: 22px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 6px;
|
padding: 0 8px;
|
||||||
box-shadow: 0 3px 8px rgba(255, 107, 107, 0.4);
|
box-shadow: 0 3px 8px rgba(255, 107, 107, 0.4);
|
||||||
border: 2px solid white;
|
border: 2px solid white;
|
||||||
z-index: 2;
|
|
||||||
animation: subtle-pulse 2s ease-in-out infinite;
|
animation: subtle-pulse 2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Стрелка для перехода в диалог */
|
||||||
|
.conversation-arrow {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #adb5bd;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-card:active .conversation-arrow {
|
||||||
|
transform: translateX(2px);
|
||||||
|
color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Неавторизованное состояние */
|
||||||
|
.not-authenticated-section {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.not-auth-card {
|
||||||
|
background: white;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
||||||
|
max-width: 400px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.not-auth-card i {
|
||||||
|
font-size: 3rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.not-auth-card h3 {
|
||||||
|
color: #343a40;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.not-auth-card p {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
/* Мягкая анимация пульсации для непрочитанных сообщений */
|
/* Мягкая анимация пульсации для непрочитанных сообщений */
|
||||||
@keyframes subtle-pulse {
|
@keyframes subtle-pulse {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
@ -545,6 +603,69 @@ const getDialogsCountText = (count) => {
|
|||||||
min-width: 0; /* Для корректной работы text-overflow */
|
min-width: 0; /* Для корректной работы text-overflow */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Адаптивные стили */
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.conversation-card {
|
||||||
|
padding: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-photo-container {
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.last-message {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 375px) {
|
||||||
|
.conversation-card {
|
||||||
|
padding: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-photo-container {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-photo-placeholder i {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ландшафтная ориентация */
|
||||||
|
@media (max-height: 450px) and (orientation: landscape) {
|
||||||
|
.chatlist-header {
|
||||||
|
height: 46px;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversations-container {
|
||||||
|
padding: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-card {
|
||||||
|
padding: 0.5rem 0.7rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Учитываем Safe Area для iPhone X+ */
|
||||||
|
@supports (padding-bottom: env(safe-area-inset-bottom)) {
|
||||||
|
.conversations-list {
|
||||||
|
padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Стили для элементов диалога, которые были в старой структуре */
|
||||||
.conversation-header {
|
.conversation-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@ -612,114 +733,4 @@ const getDialogsCountText = (count) => {
|
|||||||
0%, 100% { transform: translateY(0); }
|
0%, 100% { transform: translateY(0); }
|
||||||
50% { transform: translateY(-3px); }
|
50% { transform: translateY(-3px); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стрелка для перехода в диалог */
|
|
||||||
.conversation-arrow {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
color: #adb5bd;
|
|
||||||
transition: transform 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversation-card:active .conversation-arrow {
|
|
||||||
transform: translateX(2px);
|
|
||||||
color: #667eea;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Неавторизованное состояние */
|
|
||||||
.not-authenticated-section {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.not-auth-card {
|
|
||||||
background: white;
|
|
||||||
border-radius: 20px;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
||||||
max-width: 400px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.not-auth-card i {
|
|
||||||
font-size: 3rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
color: #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.not-auth-card h3 {
|
|
||||||
color: #343a40;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.not-auth-card p {
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
color: #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Адаптивные стили */
|
|
||||||
@media (max-width: 576px) {
|
|
||||||
.conversation-card {
|
|
||||||
padding: 0.7rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-photo-container {
|
|
||||||
width: 45px;
|
|
||||||
height: 45px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-name {
|
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.last-message {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 375px) {
|
|
||||||
.conversation-card {
|
|
||||||
padding: 0.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-photo-container {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-photo-placeholder i {
|
|
||||||
font-size: 1.3rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ландшафтная ориентация */
|
|
||||||
@media (max-height: 450px) and (orientation: landscape) {
|
|
||||||
.chatlist-header {
|
|
||||||
height: 46px;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversations-container {
|
|
||||||
padding: 0.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversation-card {
|
|
||||||
padding: 0.5rem 0.7rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Учитываем Safe Area для iPhone X+ */
|
|
||||||
@supports (padding-bottom: env(safe-area-inset-bottom)) {
|
|
||||||
.conversations-list {
|
|
||||||
padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
Loading…
x
Reference in New Issue
Block a user