281 lines
13 KiB
JavaScript
281 lines
13 KiB
JavaScript
// 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();
|
||
}, 120000); // 120000 мс = 2 минуты
|
||
|
||
console.log('🔄 Автообновление задач запущено (каждые 2 минуты)');
|
||
}
|
||
|
||
// Остановка автоматического обновления
|
||
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; |