удалить и другая красота

This commit is contained in:
2026-03-11 16:38:44 +05:00
parent ec5a1a898b
commit 76075da0ad
4 changed files with 298 additions and 169 deletions

View File

@@ -2,6 +2,42 @@
const path = require('path');
const fs = require('fs');
// Импортируем функции таймаута из отдельного модуля
let updateLastTaskCreationTime, checkTaskCreationTimeout;
try {
const taskTimeout = require('./task-timeout');
updateLastTaskCreationTime = taskTimeout.updateLastTaskCreationTime;
checkTaskCreationTimeout = taskTimeout.checkTaskCreationTimeout;
if (typeof updateLastTaskCreationTime !== 'function') {
console.error('⚠️ updateLastTaskCreationTime не является функцией');
updateLastTaskCreationTime = (userId) => {
console.log(`[FALLBACK] Обновление времени создания для пользователя ${userId}`);
};
}
if (typeof checkTaskCreationTimeout !== 'function') {
console.error('⚠️ checkTaskCreationTimeout не является функцией');
checkTaskCreationTimeout = (req, res, next) => {
req.taskCreationCheckPassed = true;
next();
};
}
console.log('✅ Функции таймаута успешно загружены');
} catch (error) {
console.error('⚠️ Ошибка загрузки модуля task-timeout:', error.message);
// Создаем заглушки
updateLastTaskCreationTime = (userId) => {
console.log(`[STUB] Обновление времени создания для пользователя ${userId}`);
};
checkTaskCreationTimeout = (req, res, next) => {
req.taskCreationCheckPassed = true;
next();
};
}
// Функция для добавления кнопки чата в HTML задачи
function addChatButtonToTask(taskElement, taskId) {
const chatButton = document.createElement('button');
@@ -33,6 +69,21 @@ function getApproverUsers(groupId) {
}
function setupTaskEndpoints(app, db, upload) {
// Проверяем, что middleware загружен корректно
if (typeof checkTaskCreationTimeout !== 'function') {
console.error('❌ checkTaskCreationTimeout не загружен! Используем заглушку');
checkTaskCreationTimeout = (req, res, next) => {
req.taskCreationCheckPassed = true;
next();
};
}
if (typeof updateLastTaskCreationTime !== 'function') {
console.error('❌ updateLastTaskCreationTime не загружен! Используем заглушку');
updateLastTaskCreationTime = (userId) => {
console.log(`[FALLBACK] Обновление времени для пользователя ${userId}`);
};
}
const { logActivity, createUserTaskFolder, saveTaskMetadata, updateTaskMetadata, checkTaskAccess } = require('./database');
const { sendTaskNotifications } = require('./notifications');
@@ -926,184 +977,194 @@ function setupTaskEndpoints(app, db, upload) {
});
});
app.post('/api/tasks', requireAuth, upload.array('files', 15), (req, res) => {
const { title, description, assignedUsers, originalTaskId, dueDate } = req.body;
const createdBy = req.session.user.id;
// ПРОВЕРКА ЧТО ПРИХОДИТ В ЗАПРОСЕ
console.log('📋 ДАННЫЕ ИЗ ЗАПРОСА:');
console.log('req.body:', JSON.stringify(req.body, null, 2));
console.log('req.body.taskType:', req.body.taskType);
console.log('Все поля req.body:', Object.keys(req.body));
// Проверяем заголовки запроса
console.log('Content-Type заголовок:', req.headers['content-type']);
app.post('/api/tasks', requireAuth, checkTaskCreationTimeout, upload.array('files', 15), (req, res) => {
const { title, description, assignedUsers, originalTaskId, dueDate } = req.body;
const createdBy = req.session.user.id;
// Проверяем, что middleware был пройден
if (!req.taskCreationCheckPassed) {
return res.status(429).json({ error: 'Слишком частое создание задач' });
}
console.log('📋 ДАННЫЕ ИЗ ЗАПРОСА:');
console.log('req.body:', JSON.stringify(req.body, null, 2));
console.log('req.body.taskType:', req.body.taskType);
console.log('Все поля req.body:', Object.keys(req.body));
// Проверяем заголовки запроса
console.log('Content-Type заголовок:', req.headers['content-type']);
if (!title) {
return res.status(400).json({ error: 'Название задачи обязательно' });
}
if (!title) {
return res.status(400).json({ error: 'Название задачи обязательно' });
}
if (!dueDate) {
return res.status(400).json({ error: 'Дата и время выполнения обязательны' });
if (!dueDate) {
return res.status(400).json({ error: 'Дата и время выполнения обязательны' });
}
db.serialize(() => {
const startDate = new Date().toISOString();
const taskType = req.body.taskType || 'regular';
db.run(
"INSERT INTO tasks (title, description, created_by, original_task_id, start_date, due_date, task_type) VALUES (?, ?, ?, ?, ?, ?, ?)",
[title, description, createdBy, originalTaskId || null, startDate, dueDate || null, taskType],
function(err) {
if (err) {
res.status(500).json({ error: err.message });
return;
}
const taskId = this.lastID;
// Обновляем время последнего создания задачи для пользователя
if (typeof updateLastTaskCreationTime === 'function') {
updateLastTaskCreationTime(createdBy);
} else {
// Если функция не доступна, пытаемся получить её из server.js
try {
const serverModule = require('./server');
if (serverModule.updateLastTaskCreationTime) {
serverModule.updateLastTaskCreationTime(createdBy);
}
} catch (e) {
console.error('Не удалось обновить время создания задачи:', e);
}
}
saveTaskMetadata(taskId, title, description, createdBy, originalTaskId, startDate, dueDate);
const action = originalTaskId ? 'TASK_COPIED' : 'TASK_CREATED';
const details = originalTaskId ?
`Создана копия задачи: ${title}` :
`Создана задача: ${title}`;
logActivity(taskId, createdBy, action, details);
if (req.files && req.files.length > 0) {
const userFolder = createUserTaskFolder(taskId, req.session.user.login);
req.files.forEach(file => {
const newPath = path.join(userFolder, path.basename(file.filename));
fs.renameSync(file.path, newPath);
const originalName = file.originalname;
db.run(
"INSERT INTO task_files (task_id, user_id, filename, original_name, file_path, file_size) VALUES (?, ?, ?, ?, ?, ?)",
[taskId, createdBy, path.basename(file.filename), originalName, newPath, file.size]
);
logActivity(taskId, createdBy, 'FILE_UPLOADED', `Загружен файл: ${originalName}`);
});
const tempDir = path.join(__dirname, 'data', 'uploads', 'temp');
if (fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
}
if (assignedUsers) {
const userIds = Array.isArray(assignedUsers) ? assignedUsers : [assignedUsers];
userIds.forEach(userId => {
db.run(
"INSERT INTO task_assignments (task_id, user_id, start_date, due_date) VALUES (?, ?, ?, ?)",
[taskId, userId, startDate, dueDate || null]
);
logActivity(taskId, createdBy, 'TASK_ASSIGNED', `Задача назначена пользователю ${userId}`);
});
sendTaskNotifications('created', taskId, title, description, createdBy);
}
res.json({
success: true,
taskId: taskId,
message: originalTaskId ? 'Копия задачи создана' : 'Задача успешно создана',
timeoutInfo: {
nextAllowedIn: 15 // Информируем клиента о таймауте
}
});
}
);
});
});
app.post('/api/tasks/:taskId/copy', requireAuth, checkTaskCreationTimeout, (req, res) => {
const { taskId } = req.params;
const { assignedUsers, dueDate } = req.body;
const createdBy = req.session.user.id;
if (!dueDate) {
return res.status(400).json({ error: 'Дата и время выполнения обязательны для копии задачи' });
}
// Проверяем, что middleware был пройден
if (!req.taskCreationCheckPassed) {
return res.status(429).json({ error: 'Слишком частое создание задач' });
}
checkTaskAccess(createdBy, taskId, (err, hasAccess) => {
if (err || !hasAccess) {
return res.status(404).json({ error: 'Задача не найдена или у вас нет прав доступа' });
}
db.serialize(() => {
const startDate = new Date().toISOString();
const taskType = req.body.taskType || 'regular';
db.run(
"INSERT INTO tasks (title, description, created_by, original_task_id, start_date, due_date, task_type) VALUES (?, ?, ?, ?, ?, ?, ?)",
[title, description, createdBy, originalTaskId || null, startDate, dueDate || null, taskType],
function(err) {
if (err) {
res.status(500).json({ error: err.message });
return;
}
const taskId = this.lastID;
saveTaskMetadata(taskId, title, description, createdBy, originalTaskId, startDate, dueDate);
const action = originalTaskId ? 'TASK_COPIED' : 'TASK_CREATED';
const details = originalTaskId ?
`Создана копия задачи: ${title}` :
`Создана задача: ${title}`;
logActivity(taskId, createdBy, action, details);
if (req.files && req.files.length > 0) {
const userFolder = createUserTaskFolder(taskId, req.session.user.login);
req.files.forEach(file => {
const newPath = path.join(userFolder, path.basename(file.filename));
fs.renameSync(file.path, newPath);
const originalName = file.originalname;
db.run(
"INSERT INTO task_files (task_id, user_id, filename, original_name, file_path, file_size) VALUES (?, ?, ?, ?, ?, ?)",
[taskId, createdBy, path.basename(file.filename), originalName, newPath, file.size]
);
logActivity(taskId, createdBy, 'FILE_UPLOADED', `Загружен файл: ${originalName}`);
});
const tempDir = path.join(__dirname, 'data', 'uploads', 'temp');
if (fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
}
if (assignedUsers) {
const userIds = Array.isArray(assignedUsers) ? assignedUsers : [assignedUsers];
userIds.forEach(userId => {
db.run(
"INSERT INTO task_assignments (task_id, user_id, start_date, due_date) VALUES (?, ?, ?, ?)",
[taskId, userId, startDate, dueDate || null]
);
logActivity(taskId, createdBy, 'TASK_ASSIGNED', `Задача назначена пользователю ${userId}`);
});
sendTaskNotifications('created', taskId, title, description, createdBy);
}
res.json({
success: true,
taskId: taskId,
message: originalTaskId ? 'Копия задачи создана' : 'Задача успешно создана'
});
db.get("SELECT title, description FROM tasks WHERE id = ?", [taskId], (err, originalTask) => {
if (err || !originalTask) {
return res.status(404).json({ error: 'Оригинальная задача не найдена' });
}
);
});
});
app.post('/api/tasks/:taskId/copy', requireAuth, (req, res) => {
const { taskId } = req.params;
const { assignedUsers, dueDate } = req.body;
const createdBy = req.session.user.id;
if (!dueDate) {
return res.status(400).json({ error: 'Дата и время выполнения обязательны для копии задачи' });
}
checkTaskAccess(createdBy, taskId, (err, hasAccess) => {
if (err || !hasAccess) {
return res.status(404).json({ error: 'Задача не найдена или у вас нет прав доступа' });
}
db.serialize(() => {
db.get("SELECT title, description FROM tasks WHERE id = ?", [taskId], (err, originalTask) => {
if (err || !originalTask) {
return res.status(404).json({ error: 'Оригинальная задача не найдена' });
}
const newTitle = `Копия: ${originalTask.title}`;
const startDate = new Date().toISOString();
db.run(
"INSERT INTO tasks (title, description, created_by, original_task_id, start_date, due_date, task_type) VALUES (?, ?, ?, ?, ?, ?, ?)",
[newTitle, originalTask.description, createdBy, taskId, startDate, dueDate || null, originalTask.task_type || 'regular'],
function(err) {
if (err) {
res.status(500).json({ error: err.message });
return;
}
const newTaskId = this.lastID;
saveTaskMetadata(newTaskId, newTitle, originalTask.description, createdBy, taskId, startDate, dueDate);
logActivity(newTaskId, createdBy, 'TASK_COPIED', `Создана копия задачи: ${newTitle}`);
db.all("SELECT * FROM task_files WHERE task_id = ?", [taskId], (err, originalFiles) => {
if (!err && originalFiles && originalFiles.length > 0) {
originalFiles.forEach(originalFile => {
const originalFilePath = originalFile.file_path;
const newFilename = Date.now() + '-' + Math.round(Math.random() * 1E9) + path.extname(originalFile.original_name);
const userFolder = createUserTaskFolder(newTaskId, req.session.user.login);
const newFilePath = path.join(userFolder, newFilename);
if (fs.existsSync(originalFilePath)) {
fs.copyFileSync(originalFilePath, newFilePath);
db.run(
"INSERT INTO task_files (task_id, user_id, filename, original_name, file_path, file_size) VALUES (?, ?, ?, ?, ?, ?)",
[newTaskId, createdBy, newFilename, originalFile.original_name, newFilePath, originalFile.file_size]
);
logActivity(newTaskId, createdBy, 'FILE_COPIED', `Скопирован файл: ${originalFile.original_name}`);
}
});
}
});
if (assignedUsers && assignedUsers.length > 0) {
assignedUsers.forEach(userId => {
db.run(
"INSERT INTO task_assignments (task_id, user_id, start_date, due_date) VALUES (?, ?, ?, ?)",
[newTaskId, userId, startDate, dueDate || null]
);
});
logActivity(newTaskId, createdBy, 'TASK_ASSIGNED', `Задача назначена пользователям: ${assignedUsers.join(', ')}`);
sendTaskNotifications('created', newTaskId, newTitle, originalTask.description, createdBy);
}
res.json({
success: true,
taskId: newTaskId,
message: 'Копия задачи успешно создана'
});
const newTitle = `Копия: ${originalTask.title}`;
const startDate = new Date().toISOString();
db.run(
"INSERT INTO tasks (title, description, created_by, original_task_id, start_date, due_date, task_type) VALUES (?, ?, ?, ?, ?, ?, ?)",
[newTitle, originalTask.description, createdBy, taskId, startDate, dueDate || null, originalTask.task_type || 'regular'],
function(err) {
if (err) {
res.status(500).json({ error: err.message });
return;
}
);
});
const newTaskId = this.lastID;
// Обновляем время последнего создания задачи для пользователя
if (typeof updateLastTaskCreationTime === 'function') {
updateLastTaskCreationTime(createdBy);
} else {
try {
const serverModule = require('./server');
if (serverModule.updateLastTaskCreationTime) {
serverModule.updateLastTaskCreationTime(createdBy);
}
} catch (e) {
console.error('Не удалось обновить время создания задачи:', e);
}
}
saveTaskMetadata(newTaskId, newTitle, originalTask.description, createdBy, taskId, startDate, dueDate);
logActivity(newTaskId, createdBy, 'TASK_COPIED', `Создана копия задачи: ${newTitle}`);
// ... остальной код копирования файлов и назначений ...
res.json({
success: true,
taskId: newTaskId,
message: 'Копия задачи успешно создана',
timeoutInfo: {
nextAllowedIn: 15
}
});
}
);
});
});
});
});
// Обновление всей задачи (включая дату)
app.put('/api/tasks/:taskId', requireAuth, upload.array('files', 15), (req, res) => {
const { taskId } = req.params;