This commit is contained in:
Professional 2025-05-26 01:05:41 +07:00
parent c04306a871
commit d0f21b566b
3 changed files with 78 additions and 28 deletions

View File

@ -108,23 +108,42 @@ const getReportById = async (req, res, next) => {
try {
const { id } = req.params;
// Валидация ObjectId
if (!id || !id.match(/^[0-9a-fA-F]{24}$/)) {
const error = new Error('Неверный ID жалобы');
error.statusCode = 400;
return next(error);
}
console.log(`[REPORT_CTRL] Поиск жалобы с ID: ${id}`);
const report = await Report.findById(id)
.populate('reporter', 'name email photos')
.populate('reportedUser', 'name email photos isActive')
.populate('reviewedBy', 'name email');
if (!report) {
console.log(`[REPORT_CTRL] Жалоба с ID ${id} не найдена`);
const error = new Error('Жалоба не найдена');
error.statusCode = 404;
return next(error);
}
// Преобразуем adminComment в adminNotes для фронтенда
console.log(`[REPORT_CTRL] Жалоба найдена: ${report._id}, статус: ${report.status}`);
// Преобразуем поля для совместимости с фронтендом
const reportResponse = report.toObject();
// Преобразуем adminComment в adminNotes
if (reportResponse.adminComment) {
reportResponse.adminNotes = reportResponse.adminComment;
}
// Преобразуем reviewedAt в resolvedAt
if (reportResponse.reviewedAt) {
reportResponse.resolvedAt = reportResponse.reviewedAt;
}
res.json(reportResponse);
} catch (error) {
@ -142,8 +161,26 @@ const updateReportStatus = async (req, res, next) => {
const { status, adminNotes } = req.body;
const adminId = req.user._id;
// Валидация ObjectId
if (!id || !id.match(/^[0-9a-fA-F]{24}$/)) {
const error = new Error('Неверный ID жалобы');
error.statusCode = 400;
return next(error);
}
// Валидация статуса
const validStatuses = ['pending', 'reviewed', 'resolved', 'dismissed'];
if (!status || !validStatuses.includes(status)) {
const error = new Error('Неверный статус жалобы');
error.statusCode = 400;
return next(error);
}
console.log(`[REPORT_CTRL] Обновление жалобы ${id} на статус: ${status} администратором ${adminId}`);
const report = await Report.findById(id);
if (!report) {
console.log(`[REPORT_CTRL] Жалоба с ID ${id} не найдена для обновления`);
const error = new Error('Жалоба не найдена');
error.statusCode = 404;
return next(error);
@ -163,7 +200,7 @@ const updateReportStatus = async (req, res, next) => {
await report.save();
console.log(`[REPORT_CTRL] Жалоба ${id} обновлена администратором ${adminId}, статус: ${status}`);
console.log(`[REPORT_CTRL] Жалоба ${id} успешно обновлена администратором ${adminId}, новый статус: ${status}`);
// Возвращаем обновленную жалобу с заполненными связями
const updatedReport = await Report.findById(id)
@ -171,12 +208,19 @@ const updateReportStatus = async (req, res, next) => {
.populate('reportedUser', 'name email isActive')
.populate('reviewedBy', 'name email');
// Преобразуем adminComment в adminNotes для фронтенда
// Преобразуем поля для совместимости с фронтендом
const reportResponse = updatedReport.toObject();
// Преобразуем adminComment в adminNotes
if (reportResponse.adminComment) {
reportResponse.adminNotes = reportResponse.adminComment;
}
// Преобразуем reviewedAt в resolvedAt
if (reportResponse.reviewedAt) {
reportResponse.resolvedAt = reportResponse.reviewedAt;
}
res.json(reportResponse);
} catch (error) {

View File

@ -136,7 +136,7 @@
<script>
import { ref, onMounted } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import axios from 'axios';
import api from '@/services/api';
export default {
name: 'AdminReportDetail',
@ -163,17 +163,19 @@ export default {
error.value = null;
try {
const token = localStorage.getItem('userToken');
const response = await axios.get(`/api/admin/reports/${props.id}`, {
headers: {
Authorization: `Bearer ${token}`
}
});
console.log('[AdminReportDetail] Загружаем жалобу с ID:', props.id);
const response = await api.getReportById(props.id);
report.value = response.data;
console.log('[AdminReportDetail] Жалоба загружена:', response.data);
} catch (err) {
console.error('Ошибка при загрузке жалобы:', err);
error.value = 'Ошибка при загрузке информации о жалобе.';
if (err.response?.status === 404) {
error.value = 'Жалоба не найдена.';
} else if (err.response?.status === 403) {
error.value = 'У вас нет прав для просмотра этой жалобы.';
} else {
error.value = err.response?.data?.message || 'Ошибка при загрузке информации о жалобе.';
}
} finally {
loading.value = false;
}
@ -184,14 +186,10 @@ export default {
updating.value = true;
try {
const token = localStorage.getItem('userToken');
const response = await axios.put(`/api/admin/reports/${props.id}`, {
console.log('[AdminReportDetail] Обновляем статус жалобы:', status);
const response = await api.updateReportStatus(props.id, {
status,
adminNotes: adminNotes.value
}, {
headers: {
Authorization: `Bearer ${token}`
}
});
// Обновляем локальные данные
@ -202,10 +200,12 @@ export default {
showDismissModal.value = false;
adminNotes.value = '';
console.log('[AdminReportDetail] Статус жалобы обновлен успешно');
alert(`Жалоба успешно ${status === 'resolved' ? 'рассмотрена' : 'отклонена'}`);
} catch (err) {
console.error('Ошибка при обновлении статуса жалобы:', err);
alert('Ошибка при обновлении статуса жалобы');
const errorMessage = err.response?.data?.message || 'Ошибка при обновлении статуса жалобы';
alert(errorMessage);
} finally {
updating.value = false;
}
@ -242,6 +242,7 @@ export default {
fake_profile: 'Фальшивый профиль',
harassment: 'Домогательства',
spam: 'Спам',
offensive_behavior: 'Оскорбительное поведение',
underage: 'Несовершеннолетний',
other: 'Другое'
};
@ -255,6 +256,7 @@ export default {
fake_profile: 'reason-fake',
harassment: 'reason-harassment',
spam: 'reason-spam',
offensive_behavior: 'reason-offensive',
underage: 'reason-underage',
other: 'reason-other'
};
@ -462,6 +464,7 @@ h2 {
.reason-fake { background-color: #fff3cd; color: #856404; }
.reason-harassment { background-color: #d1ecf1; color: #0c5460; }
.reason-spam { background-color: #d4edda; color: #155724; }
.reason-offensive { background-color: #f8d7da; color: #721c24; }
.reason-underage { background-color: #f8d7da; color: #721c24; }
.reason-other { background-color: #e2e3e5; color: #383d41; }

View File

@ -102,7 +102,7 @@
<script>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import axios from 'axios';
import api from '@/services/api';
export default {
name: 'AdminReports',
@ -135,19 +135,19 @@ export default {
params.status = statusFilter.value;
}
const token = localStorage.getItem('userToken');
const response = await axios.get(`/api/admin/reports`, {
params,
headers: {
Authorization: `Bearer ${token}`
}
});
console.log('[AdminReports] Загружаем жалобы с параметрами:', params);
const response = await api.getReports(params);
reports.value = response.data.reports;
pagination.value = response.data.pagination;
console.log('[AdminReports] Жалобы загружены:', response.data);
} catch (err) {
console.error('Ошибка при загрузке жалоб:', err);
error.value = 'Ошибка при загрузке списка жалоб. Пожалуйста, попробуйте позже.';
if (err.response?.status === 403) {
error.value = 'У вас нет прав для просмотра жалоб.';
} else {
error.value = err.response?.data?.message || 'Ошибка при загрузке списка жалоб. Пожалуйста, попробуйте позже.';
}
} finally {
loading.value = false;
}
@ -179,6 +179,7 @@ export default {
fake_profile: 'Фальшивый профиль',
harassment: 'Домогательства',
spam: 'Спам',
offensive_behavior: 'Оскорбительное поведение',
underage: 'Несовершеннолетний',
other: 'Другое'
};
@ -192,6 +193,7 @@ export default {
fake_profile: 'reason-fake',
harassment: 'reason-harassment',
spam: 'reason-spam',
offensive_behavior: 'reason-offensive',
underage: 'reason-underage',
other: 'reason-other'
};
@ -364,6 +366,7 @@ h2::before {
.reason-fake { background-color: #fff3cd; color: #856404; }
.reason-harassment { background-color: #d1ecf1; color: #0c5460; }
.reason-spam { background-color: #d4edda; color: #155724; }
.reason-offensive { background-color: #f8d7da; color: #721c24; }
.reason-underage { background-color: #f8d7da; color: #721c24; }
.reason-other { background-color: #e2e3e5; color: #383d41; }