Files
minicrm/public/loadMyCreatedTasks.js
2026-03-04 12:09:40 +05:00

281 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// loadMyCreatedTasks.js - Задачи, созданные пользователем и назначенные ему
// Глобальные переменные
let expandedMyTasks = new Set();
let updateInterval = null;
let isUpdating = false;
// Показать секцию "Мои задачи (как автор)"
function showMyTasksSection() {
showSection('mytasks');
window.currentTaskView = 'my_assigned';
loadTasks();
startAutoUpdate();
}
// Показать секцию "Задачи для исполнения"
function showRunTasksSection() {
showSection('runtasks');
window.currentTaskView = 'assigned_to_me';
loadTasks();
startAutoUpdate();
}
// Остановка автообновления при уходе с секции
function hideTasksSection() {
stopAutoUpdate();
}
// Запуск автоматического обновления
function startAutoUpdate() {
// Останавливаем предыдущий интервал, если был
stopAutoUpdate();
// Запускаем новый интервал (каждые 15 секунд)
updateInterval = setInterval(() => {
autoUpdateTasks();
}, 15000); // 15000 мс = 15 секунд
console.log('🔄 Автообновление задач запущено (каждые 15 сек)');
}
// Остановка автоматического обновления
function stopAutoUpdate() {
if (updateInterval) {
clearInterval(updateInterval);
updateInterval = null;
console.log('⏹️ Автообновление задач остановлено');
}
}
// Функция автоматического обновления
async function autoUpdateTasks() {
// Предотвращаем множественные обновления
if (isUpdating) {
console.log('⏳ Обновление уже выполняется, пропускаем...');
return;
}
// Проверяем, активна ли секция
const mytasksSection = document.getElementById('mytasks-section');
const runtasksSection = document.getElementById('runtasks-section');
if ((!mytasksSection || !mytasksSection.classList.contains('active')) &&
(!runtasksSection || !runtasksSection.classList.contains('active'))) {
console.log('⏸️ Секция неактивна, автообновление приостановлено');
stopAutoUpdate();
return;
}
isUpdating = true;
try {
console.log('🔄 Автообновление задач...', new Date().toLocaleTimeString());
await loadTasks(); // просто перезагружаем с текущими фильтрами
// Показываем уведомление об обновлении
showUpdateNotification();
} catch (error) {
console.error('❌ Ошибка автообновления:', error);
} finally {
isUpdating = false;
}
}
// Показ уведомления об обновлении
function showUpdateNotification() {
const notification = document.createElement('div');
notification.className = 'update-notification';
notification.innerHTML = `
<span>🔄 Данные обновлены</span>
<span class="update-time">${new Date().toLocaleTimeString()}</span>
`;
document.body.appendChild(notification);
// Анимация появления и исчезновения
setTimeout(() => {
notification.classList.add('show');
}, 10);
setTimeout(() => {
notification.classList.remove('show');
setTimeout(() => {
notification.remove();
}, 300);
}, 2000);
}
// Функция фильтрации для "Мои задачи" - просто перезагружает с текущими фильтрами
function filterMyTasks() {
loadTasks();
}
// Функция фильтрации для "Задачи для исполнения"
function filterRunTasks() {
loadTasks();
}
// Рендеринг для "Мои задачи"
function renderMyTasks() {
const container = document.getElementById('mytasks-list');
if (!container) return;
if (!window.tasks || window.tasks.length === 0) {
container.innerHTML = '<div class="loading">У вас пока нет созданных задач</div>';
return;
}
// Используем общую функцию рендеринга, если она есть
if (typeof renderTasksInContainer === 'function') {
renderTasksInContainer('mytasks-list', window.tasks);
} else {
// Запасной вариант: рендерим прямо здесь (упрощённо)
renderMyTasksSimple(window.tasks);
}
}
// Упрощённый рендеринг для "Мои задачи" (если нет общей функции)
function renderMyTasksSimple(tasks) {
const container = document.getElementById('mytasks-list');
// Сортируем задачи по дате создания (новые сверху)
const sortedTasks = [...tasks].sort((a, b) =>
new Date(b.created_at || 0) - new Date(a.created_at || 0)
);
container.innerHTML = sortedTasks.map(task => {
const isExpanded = expandedMyTasks.has(task.id);
const overallStatus = getTaskOverallStatus(task);
const statusClass = getStatusClass(overallStatus);
const isClosed = task.closed_at !== null;
const isCopy = task.original_task_id !== null;
const timeLeftInfo = getTimeLeftInfo(task);
return `
<div class="task-card" data-task-id="${task.id}">
<div class="task-header">
<div class="task-title" onclick="toggleMyTask(${task.id})" style="cursor: pointer; display: flex; justify-content: space-between; align-items: center;">
<div style="flex: 1;">
<span class="task-number">Задача №${task.id}</span>
<strong>${task.title || 'Без названия'}</strong>
${task.task_type ? `<span class="task-type-badge ${task.task_type}">${getTaskTypeDisplayName(task.task_type)}</span>` : ''}
${isClosed ? '<span class="closed-badge">Закрыта</span>' : ''}
${isCopy ? '<span class="copy-badge">Копия</span>' : ''}
${timeLeftInfo ? `<span class="deadline-badge ${timeLeftInfo.class}">${timeLeftInfo.text}</span>` : ''}
${task.assignments && task.assignments.length > 0 ?
`<span class="task-number">${task.assignments.map(a => a.user_name).join(', ')}</span>` : ''
}
</div>
<span class="task-status ${statusClass}">
Выполнить до: ${formatDateTime(task.due_date || task.created_at)}
</span>
<div class="expand-icon" style="margin-left: 10px; transition: transform 0.3s; transform: rotate(${isExpanded ? '180deg' : '0deg'});">
</div>
</div>
</div>
<div class="task-content ${isExpanded ? 'expanded' : ''}">
${isExpanded ? `
<div class="task-actions">
<button class="copy-btn" onclick="openTaskChat(${task.id})" title="Открыть чат">💬</button>
<button class="add-file-btn" onclick="openAddFileModal(${task.id})" title="Добавить файл">📎</button>
${currentUser && currentUser.login === 'minicrm' ?
`<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.role === 'tasks' || currentUser.role === 'admin') ?
`<button class="manage-assignees-btn" onclick="assignAdd_openModal(${task.id})" title="Управление исполнителями">🧑‍💼➕Добавить</button>` : ''
}
${currentUser && (currentUser.role === 'tasks' || currentUser.role === 'admin') ?
`<button class="manage-assignees-btn" onclick="assignRemove_openModal(${task.id})" title="Управление исполнителями">🧑‍💼❌Удалить</button>` : ''
}
<button class="copy-btn" onclick="openCopyModal(${task.id})" title="Создать копию">📋</button>
${currentUser && currentUser.login === 'minicrm' ?
`<button class="rework-btn" onclick="openReworkModal(${task.id})" title="Вернуть на доработку">🔄</button>` : ''
}
${currentUser && currentUser.login === 'minicrm' ?
`<button class="close-btn" onclick="closeTask(${task.id})" title="Закрыть задачу">🔒</button>` : ''
}
<button class="delete-btn" onclick="deleteTask(${task.id})" title="Удалить">🗑️</button>
</div>
` : ''}
${isCopy && task.original_task_title ? `
<div class="task-original">
<small>Оригинал: "${task.original_task_title}" (создал: ${task.original_creator_name})</small>
</div>
` : ''}
<div class="task-description">${task.description || 'Нет описания'}</div>
${task.rework_comment ? `
<div class="rework-comment">
<strong>Комментарий к доработке:</strong> ${task.rework_comment}
</div>
` : ''}
<div class="file-list" id="files-${task.id}">
<strong>Файлы:</strong>
${task.files && task.files.length > 0 ?
(typeof renderGroupedFilesWithDelete === 'function' ? renderGroupedFilesWithDelete(task) : renderGroupedFiles(task))
: '<span class="no-files">нет файлов</span>'
}
</div>
<div class="task-assignments">
<strong>Исполнители:</strong>
${task.assignments && task.assignments.length > 0 ?
renderAssignmentList(task.assignments, task.id, true) :
'<div>Не назначены</div>'
}
</div>
</div>
<div class="task-meta">
<small>
Создана: ${formatDateTime(task.start_date || task.created_at)}
| Выполнить до: ${formatDateTime(task.due_date || task.created_at)}
| Автор: ${task.creator_name}
| Тип: ${task.task_type ? `<span class="task-type-badge ${task.task_type}">${getTaskTypeDisplayName(task.task_type)}</span>` : ''}
</small>
${task.closed_at ? `<br><small>Закрыта: ${formatDateTime(task.closed_at)}</small>` : ''}
</div>
</div>
`;
}).join('');
// Загружаем файлы для развернутых задач
expandedMyTasks.forEach(taskId => {
if (window.tasks.some(t => t.id == taskId)) {
loadTaskFiles(taskId);
}
});
}
// Функция для переключения развернутого состояния задачи
function toggleMyTask(taskId) {
if (expandedMyTasks.has(taskId)) {
expandedMyTasks.delete(taskId);
} else {
expandedMyTasks.add(taskId);
loadTaskFiles(taskId);
}
renderMyTasks();
}
// Остальные вспомогательные функции (getStatusClass, getTaskTypeDisplayName, formatDateTime, renderAssignment, filterAssignments, openAddFileModal, closeAddFileModal, openTaskChat, openEditModal, openCopyModal, openReworkModal, closeTask, deleteTask, updateStatus) остаются без изменений
// ...
// Экспортируем функции в глобальную область
window.showMyTasksSection = showMyTasksSection;
window.showRunTasksSection = showRunTasksSection;
window.filterMyTasks = filterMyTasks;
window.filterRunTasks = filterRunTasks;
window.toggleMyTask = toggleMyTask;
window.renderMyTasks = renderMyTasks;