добавление фаилов исполнителем

This commit is contained in:
2026-02-05 16:39:49 +05:00
parent 689000798e
commit 699bdf6961
2 changed files with 101 additions and 30 deletions

View File

@@ -82,7 +82,7 @@ function renderTasks() {
<div class="task-content ${isExpanded ? 'expanded' : ''}"> <div class="task-content ${isExpanded ? 'expanded' : ''}">
<div class="task-actions"> <div class="task-actions">
${!isDeleted && !isClosed ? ` ${!isDeleted && !isClosed ? `
${canEdit ? `<button class="add-file-btn" onclick="openAddFileModal(${task.id})" title="Добавить файл">📎</button>` : ''} <button class="add-file-btn" onclick="openAddFileModal(${task.id})" title="Добавить файл">📎</button>
${currentUser && currentUser.login === 'kalugin.o' ? `<button class="edit-btn" onclick="openEditModal(${task.id})" title="Редактировать">✏️</button>` : ''} ${currentUser && currentUser.login === 'kalugin.o' ? `<button class="edit-btn" onclick="openEditModal(${task.id})" title="Редактировать">✏️</button>` : ''}
${currentUser && currentUser.login === 'kalugin.o' ? `<button class="manage-assignees-btn" onclick="openManageAssigneesModal(${task.id})" title="Управление исполнителями">👥</button>` : ''} ${currentUser && currentUser.login === 'kalugin.o' ? `<button class="manage-assignees-btn" onclick="openManageAssigneesModal(${task.id})" title="Управление исполнителями">👥</button>` : ''}
<button class="copy-btn" onclick="openCopyModal(${task.id})" title="Создать копию">📋</button> <button class="copy-btn" onclick="openCopyModal(${task.id})" title="Создать копию">📋</button>
@@ -113,13 +113,49 @@ ${currentUser && currentUser.login === 'kalugin.o' ? `<button class="manage-assi
` : ''} ` : ''}
<div class="file-list" id="files-${task.id}"> <div class="file-list" id="files-${task.id}">
<strong>Файлы:</strong> <strong>Файлы:</strong>
${task.files && task.files.length > 0 ? ${task.files && task.files.length > 0 ?
`<div class="file-icons-container">${task.files.map(file => renderFileIcon(file)).join('')}</div>` : `<div class="file-icons-container">
'<span class="no-files">нет файлов</span>' ${task.files.map(file => {
} // Определяем, может ли пользователь видеть этот файл
</div> let canSeeFile = false;
// 1. Администратор видит все файлы
if (currentUser.role === 'admin') {
canSeeFile = true;
}
// 2. Создатель задачи видит все файлы
else if (parseInt(task.created_by) === currentUser.id) {
canSeeFile = true;
}
// 3. Исполнитель видит:
// - Файлы, загруженные создателем
// - Свои файлы
else {
// Получаем ID создателя задачи
const creatorId = parseInt(task.created_by);
// Файл загружен создателем
if (parseInt(file.user_id) === creatorId) {
canSeeFile = true;
}
// Файл загружен текущим пользователем (исполнителем)
else if (parseInt(file.user_id) === currentUser.id) {
canSeeFile = true;
}
// Если файл загружен другим исполнителем - не показываем
else {
canSeeFile = false;
}
}
return canSeeFile ? renderFileIcon(file) : '';
}).join('')}
</div>` :
'<span class="no-files">нет файлов</span>'
}
</div>
<div class="task-assignments"> <div class="task-assignments">
@@ -556,10 +592,11 @@ function openAddFileModal(taskId) {
method: 'POST', method: 'POST',
body: formData body: formData
}); });
console.log('Попытка 1');
if (!response.ok) { if (!response.ok) {
// Попробуем с полем 'file' // Попробуем с полем 'file'
console.log('Попытка с именем поля "file"...'); console.log('Попытка 2 с именем поля "file"...');
formData.delete('files'); formData.delete('files');
formData.append('file', file); formData.append('file', file);
@@ -568,7 +605,7 @@ function openAddFileModal(taskId) {
body: formData body: formData
}); });
} }
if (response.ok) { if (response.ok) {
alert('Файл успешно добавлен'); alert('Файл успешно добавлен');
await loadTaskFiles(taskId); await loadTaskFiles(taskId);

View File

@@ -1270,43 +1270,77 @@ app.get('/api/document-approval-tasks', requireAuth, (req, res) => {
}); });
}); });
app.post('/api/tasks/:taskId/files', requireAuth, upload.array('files', 15), (req, res) => { app.post('/api/tasks/:taskId/files', requireAuth, upload.array('files', 15), (req, res) => {
const { taskId } = req.params; const { taskId } = req.params;
const userId = req.session.user.id; const userId = req.session.user.id;
if (!req.files || req.files.length === 0) { if (!req.files || req.files.length === 0) {
return res.status(400).json({ error: 'Нет файлов для загрузки' }); return res.status(400).json({ error: 'Нет файлов для загрузки' });
}
// Проверяем доступ к задаче через checkTaskAccess
const { checkTaskAccess } = require('./database');
checkTaskAccess(userId, taskId, (err, hasAccess) => {
if (err || !hasAccess) {
return res.status(403).json({ error: 'Нет доступа к задаче' });
} }
db.get("SELECT created_by, status, closed_at FROM tasks WHERE id = ?", [taskId], (err, task) => { // Дополнительно проверяем, что задача активна
db.get("SELECT status, closed_at FROM tasks WHERE id = ?", [taskId], (err, task) => {
if (err || !task) { if (err || !task) {
return res.status(404).json({ error: 'Задача не найдена' }); return res.status(404).json({ error: 'Задача не найдена' });
} }
// Проверяем права на загрузку файлов if (task.closed_at) {
if (!canUserEditTask(task, req.session.user)) { return res.status(400).json({ error: 'Задача уже закрыта' });
return res.status(403).json({ error: 'У вас нет прав для загрузки файлов в эту задачу' });
} }
const userFolder = createUserTaskFolder(taskId, req.session.user.login); const userFolder = createUserTaskFolder(taskId, req.session.user.login);
req.files.forEach(file => { const uploadPromises = req.files.map(file => {
const newPath = path.join(userFolder, path.basename(file.filename)); return new Promise((resolve, reject) => {
fs.renameSync(file.path, newPath); const newPath = path.join(userFolder, path.basename(file.filename));
fs.renameSync(file.path, newPath);
const originalName = file.originalname; const originalName = file.originalname;
db.run( db.run(
"INSERT INTO task_files (task_id, user_id, filename, original_name, file_path, file_size) VALUES (?, ?, ?, ?, ?, ?)", "INSERT INTO task_files (task_id, user_id, filename, original_name, file_path, file_size) VALUES (?, ?, ?, ?, ?, ?)",
[taskId, userId, path.basename(file.filename), originalName, newPath, file.size] [taskId, userId, path.basename(file.filename), originalName, newPath, file.size],
); function(err) {
if (err) {
logActivity(taskId, userId, 'FILE_UPLOADED', `Загружен файл: ${originalName}`); reject(err);
return;
}
logActivity(taskId, userId, 'FILE_UPLOADED', `Загружен файл: ${originalName}`);
resolve({
id: this.lastID,
originalName,
size: file.size
});
}
);
});
}); });
res.json({ success: true, message: 'Файлы успешно загружены' }); Promise.all(uploadPromises)
.then((uploadedFiles) => {
res.json({
success: true,
message: 'Файлы успешно загружены',
files: uploadedFiles,
count: uploadedFiles.length
});
})
.catch((error) => {
console.error('Ошибка при загрузке файлов:', error);
res.status(500).json({ error: 'Ошибка при сохранении файлов в БД' });
});
}); });
}); });
});
// API для получения одной задачи // API для получения одной задачи
app.get('/api/tasks/:taskId', requireAuth, (req, res) => { app.get('/api/tasks/:taskId', requireAuth, (req, res) => {