diff --git a/serv_nginx/bbvue/src/views/News.vue b/serv_nginx/bbvue/src/views/News.vue index 5691854..7b4675d 100644 --- a/serv_nginx/bbvue/src/views/News.vue +++ b/serv_nginx/bbvue/src/views/News.vue @@ -216,38 +216,81 @@
- + +
{{ formErrors.title }}
+
+ {{ newsForm.title.length }}/255 + + (минимум 5 символов) + +
- -
{{ newsForm.excerpt.length }}/500
+ +
{{ formErrors.excerpt }}
+
+ {{ newsForm.excerpt.length }}/500 + + (минимум 10 символов) + +
- + +
{{ formErrors.content }}
+
+ {{ newsForm.content.length }} символов + + (минимум 50 символов) + +
- +
{{ formErrors.category }}
- + Оставьте пустым для изображения по умолчанию
@@ -255,7 +298,9 @@ - @@ -296,6 +341,12 @@ export default { category: '', image: '' }, + formErrors: { + title: '', + excerpt: '', + content: '', + category: '' + }, filters: [ { value: 'all', label: 'Все новости' }, { value: 'events', label: 'События' }, @@ -322,11 +373,74 @@ export default { filtered = this.news.filter(item => item.category === this.activeFilter) } return filtered.slice(0, this.visibleNews) + }, + // Проверка валидности формы + isFormValid() { + return this.newsForm.title.length >= 5 && + this.newsForm.title.length <= 255 && + this.newsForm.excerpt.length >= 10 && + this.newsForm.excerpt.length <= 500 && + this.newsForm.content.length >= 50 && + this.newsForm.category !== '' } }, methods: { ...mapActions(useAuthStore, ['fetchProfile']), + // Валидация формы + validateForm() { + this.clearAllErrors() + let isValid = true + + // Валидация заголовка + if (this.newsForm.title.length < 5) { + this.formErrors.title = 'Заголовок должен содержать минимум 5 символов' + isValid = false + } else if (this.newsForm.title.length > 255) { + this.formErrors.title = 'Заголовок не должен превышать 255 символов' + isValid = false + } + + // Валидация краткого описания + if (this.newsForm.excerpt.length < 10) { + this.formErrors.excerpt = 'Краткое описание должно содержать минимум 10 символов' + isValid = false + } else if (this.newsForm.excerpt.length > 500) { + this.formErrors.excerpt = 'Краткое описание не должно превышать 500 символов' + isValid = false + } + + // Валидация содержания + if (this.newsForm.content.length < 50) { + this.formErrors.content = 'Содержание должно содержать минимум 50 символов' + isValid = false + } + + // Валидация категории + if (!this.newsForm.category) { + this.formErrors.category = 'Выберите категорию' + isValid = false + } + + return isValid + }, + + // Очистка ошибок + clearAllErrors() { + this.formErrors = { + title: '', + excerpt: '', + content: '', + category: '' + } + }, + + clearFieldError(field) { + if (this.formErrors[field]) { + this.formErrors[field] = '' + } + }, + async fetchNews() { this.loading = true this.error = '' @@ -389,7 +503,7 @@ export default { if (!confirm('Удалить этот комментарий?')) return try { - await apiClient.$.delete(`/news/comments/${commentId}`) + await apiClient.delete(`/news/comments/${commentId}`) await this.fetchComments(this.selectedNews.id) await this.fetchNews() } catch (error) { @@ -407,6 +521,7 @@ export default { category: '', image: '' } + this.clearAllErrors() this.showNewsFormModal = true }, @@ -419,6 +534,7 @@ export default { category: newsItem.category, image: newsItem.image || '' } + this.clearAllErrors() this.showNewsFormModal = true if (this.showNewsModal) { this.closeNewsModal() @@ -449,6 +565,12 @@ export default { }, async submitNewsForm() { + // Предварительная валидация на фронтенде + if (!this.validateForm()) { + alert('Пожалуйста, исправьте ошибки в форме перед отправкой.') + return + } + this.newsLoading = true try { if (this.editingNews) { @@ -462,7 +584,17 @@ export default { await this.fetchNews() } catch (error) { console.error('Failed to save news:', error) - alert('Не удалось сохранить новость. Проверьте все поля и попробуйте снова.') + // Обработка ошибок валидации с бэкенда + if (error.response && error.response.status === 400) { + const errorData = error.response.data + if (typeof errorData === 'string' && errorData.includes('Validation failed')) { + alert('Ошибка валидации: проверьте, что все поля соответствуют требованиям (заголовок - минимум 5 символов, описание - минимум 10 символов, содержание - минимум 50 символов).') + } else { + alert('Ошибка при сохранении: ' + (errorData.message || errorData)) + } + } else { + alert('Не удалось сохранить новость. Проверьте все поля и попробуйте снова.') + } } finally { this.newsLoading = false } @@ -511,6 +643,7 @@ export default { closeNewsFormModal() { this.showNewsFormModal = false this.editingNews = null + this.clearAllErrors() }, shareNews(newsItem) { @@ -560,6 +693,12 @@ export default { if (this.showNewsModal) this.closeNewsModal() if (this.showNewsFormModal) this.closeNewsFormModal() } + }, + + handleAuthError() { + localStorage.removeItem('auth_token') + this.isAuthenticated = false + this.currentUser = null } }, async mounted() { @@ -578,8 +717,44 @@ export default {