1
0

Комментарии, файлы и права проекта

- Система комментариев к задачам с вложенными ответами
- Редактирование и удаление комментариев
- Прикрепление файлов к задачам и комментариям (картинки, архивы до 10 МБ)
- Система прав проекта: админ проекта может удалять чужие комментарии и файлы
- Универсальный класс FileUpload для загрузки файлов
- Защита загрузки: только автор комментария может добавлять файлы
- Каскадное удаление: задача → комментарии → файлы
- Автообновление комментариев в реальном времени
This commit is contained in:
2026-01-15 06:40:47 +07:00
parent 8ac497df63
commit 3bfa1e9e1b
25 changed files with 3353 additions and 904 deletions

View File

@@ -1,6 +1,6 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { projectsApi, usersApi } from '../api'
import { projectsApi, usersApi, authApi } from '../api'
export const useProjectsStore = defineStore('projects', () => {
// ==================== СОСТОЯНИЕ ====================
@@ -11,6 +11,7 @@ export const useProjectsStore = defineStore('projects', () => {
const users = ref([])
const loading = ref(false)
const initialized = ref(false)
const currentUser = ref(null) // Текущий авторизованный пользователь
// Текущий проект (из localStorage)
const savedProjectId = localStorage.getItem('currentProjectId')
@@ -30,6 +31,16 @@ export const useProjectsStore = defineStore('projects', () => {
return project ? Number(project.id_ready) : null
})
// ID текущего пользователя
const currentUserId = computed(() => currentUser.value?.id || null)
// Является ли текущий пользователь админом проекта
// Сервер возвращает id_admin: true только если текущий пользователь — админ
const isProjectAdmin = computed(() => {
const project = projects.value.find(p => p.id === currentProjectId.value)
return project?.id_admin === true
})
// ==================== ДЕЙСТВИЯ ====================
// Инициализация (загрузка проектов + данных активного)
const init = async () => {
@@ -74,6 +85,14 @@ export const useProjectsStore = defineStore('projects', () => {
const usersData = await usersApi.getAll()
if (usersData.success) users.value = usersData.data
// Загружаем текущего пользователя
const authData = await authApi.check()
if (authData.success && authData.user) {
// Находим полные данные пользователя (с id) из списка users
const fullUser = users.value.find(u => u.username === authData.user.username)
currentUser.value = fullUser || authData.user
}
initialized.value = true
} catch (error) {
console.error('Ошибка инициализации:', error)
@@ -108,6 +127,12 @@ export const useProjectsStore = defineStore('projects', () => {
columns.value = projectData.data.columns
departments.value = projectData.data.departments
labels.value = projectData.data.labels
// Обновляем id_admin в списке проектов (сервер возвращает true если текущий пользователь админ)
const project = projects.value.find(p => p.id === currentProjectId.value)
if (project && projectData.data.project?.id_admin === true) {
project.id_admin = true
}
}
} catch (error) {
console.error('Ошибка загрузки данных проекта:', error)
@@ -122,6 +147,7 @@ export const useProjectsStore = defineStore('projects', () => {
columns.value = []
users.value = []
currentProjectId.value = null
currentUser.value = null
initialized.value = false
localStorage.removeItem('currentProjectId')
localStorage.removeItem('currentProjectName')
@@ -137,9 +163,12 @@ export const useProjectsStore = defineStore('projects', () => {
loading,
initialized,
currentProjectId,
currentUser,
// Геттеры
currentProject,
doneColumnId,
currentUserId,
isProjectAdmin,
// Действия
init,
selectProject,