действия подписать

This commit is contained in:
2026-03-05 23:21:57 +05:00
parent c958a7f913
commit 91f408aca2
2 changed files with 18 additions and 159 deletions

View File

@@ -88,7 +88,16 @@ if (currentUser && !isDeleted && !isClosed) {
log('nav-task-actions openManageAssigneesModal not'); log('nav-task-actions openManageAssigneesModal not');
} }
} }
// Подписание (только для документов, если текущий пользователь - исполнитель)
if (!isDeleted && !isClosed && task.task_type === 'document' && currentUser && task.assignments?.some(a => parseInt(a.user_id) === currentUser.id)) {
if (typeof window.signTask === 'function') {
actions.push({
label: '✍️ Подписать',
handler: () => window.signTask(taskId, currentUser.id),
admin: true // primary_task
});
}
}
// ${currentUser && currentUser.role === 'tasks' && canEdit || currentUser.role === 'admin' // ${currentUser && currentUser.role === 'tasks' && canEdit || currentUser.role === 'admin'
// Администраторы и роль tasks // Администраторы и роль tasks
if (currentUser && (currentUser.role === 'admin' || (currentUser.role === 'tasks' && canEdit))) { if (currentUser && (currentUser.role === 'admin' || (currentUser.role === 'tasks' && canEdit))) {
@@ -122,6 +131,7 @@ if (currentUser && (currentUser.role === 'admin' || (currentUser.role === 'tasks
} }
} }
} }
// Доработка и изменение срока для необычных задач (исполнитель) // Доработка и изменение срока для необычных задач (исполнитель)
if (!isDeleted && !isClosed && task.task_type !== 'regular' && task.assignments && task.assignments.some(a => parseInt(a.user_id) === currentUser?.id)) { if (!isDeleted && !isClosed && task.task_type !== 'regular' && task.assignments && task.assignments.some(a => parseInt(a.user_id) === currentUser?.id)) {
if (typeof openReworkModal === 'function') { actions.push({ label: '🔄 Доработка', handler: () => openReworkModal(taskId),primary_task: true}); if (typeof openReworkModal === 'function') { actions.push({ label: '🔄 Доработка', handler: () => openReworkModal(taskId),primary_task: true});
@@ -131,7 +141,7 @@ if (typeof openChangeDeadlineModal === 'function') { actions.push({ label: '📅
log('nav-task-actions openChangeDeadlineModal yes'); log('nav-task-actions openChangeDeadlineModal yes');
} else {log('nav-task-actions openChangeDeadlineModal not');} } else {log('nav-task-actions openChangeDeadlineModal not');}
} }
if (currentUser && currentUser.login === 'minicrm') { if (currentUser && currentUser.login === 'minicrm') {
// Закрытие (только minicrm) // Закрытие (только minicrm)
//if (window.currentUser && window.currentUser.login === 'minicrm') { //if (window.currentUser && window.currentUser.login === 'minicrm') {

View File

@@ -1,4 +1,4 @@
// signature.js - Универсальный скрипт для подписания задач // signature.js - Универсальный скрипт для подписания задач (только логика, без встройки в интерфейс)
(function() { (function() {
'use strict'; 'use strict';
@@ -9,7 +9,7 @@
usersEndpoint: '/api/users', usersEndpoint: '/api/users',
replaceEndpoint: '/api/tasks/${taskId}/replace-assignee', replaceEndpoint: '/api/tasks/${taskId}/replace-assignee',
replaceAllEndpoint: '/api/tasks/${taskId}/replace-all-assignees', replaceAllEndpoint: '/api/tasks/${taskId}/replace-all-assignees',
taskTypeDocument: 'document' // Тип задачи "Документ" taskTypeDocument: 'document'
}; };
// Текущий пользователь // Текущий пользователь
@@ -24,9 +24,6 @@
const data = await response.json(); const data = await response.json();
if (data.user) { if (data.user) {
currentUser = data.user; currentUser = data.user;
////console.log('✅ Signature: текущий пользователь', currentUser);
// Проверяем, является ли пользователь подписантом
await checkIfUserIsSigner(); await checkIfUserIsSigner();
} }
return currentUser; return currentUser;
@@ -39,19 +36,13 @@
// Проверка, является ли текущий пользователь подписантом // Проверка, является ли текущий пользователь подписантом
async function checkIfUserIsSigner() { async function checkIfUserIsSigner() {
if (!currentUser) return false; if (!currentUser) return false;
try { try {
// Получаем всех подписантов
const signers = await getSigners(); const signers = await getSigners();
// Проверяем, есть ли текущий пользователь в списке подписантов
isCurrentUserSigner = signers.some(signer => isCurrentUserSigner = signers.some(signer =>
signer.id === currentUser.id || signer.id === currentUser.id ||
signer.login === currentUser.login || signer.login === currentUser.login ||
signer.name === currentUser.name signer.name === currentUser.name
); );
////console.log('✅ Signature: пользователь является подписантом?', isCurrentUserSigner);
return isCurrentUserSigner; return isCurrentUserSigner;
} catch (error) { } catch (error) {
console.error('❌ Signature: ошибка проверки подписанта', error); console.error('❌ Signature: ошибка проверки подписанта', error);
@@ -64,7 +55,6 @@
try { try {
const response = await fetch(CONFIG.apiEndpoint); const response = await fetch(CONFIG.apiEndpoint);
if (!response.ok) return await getSignersFallback(); if (!response.ok) return await getSignersFallback();
const data = await response.json(); const data = await response.json();
const signers = data.filter(user => const signers = data.filter(user =>
user.is_active && ( user.is_active && (
@@ -73,7 +63,6 @@
user.ldap_group?.toLowerCase().includes(CONFIG.signerGroup.toLowerCase()) user.ldap_group?.toLowerCase().includes(CONFIG.signerGroup.toLowerCase())
) )
); );
return signers.map(s => ({ return signers.map(s => ({
id: s.user_id, id: s.user_id,
name: s.user_name || s.login || 'Неизвестно', name: s.user_name || s.login || 'Неизвестно',
@@ -99,9 +88,7 @@
// Основная функция подписания // Основная функция подписания
window.signTask = async function(taskId, userId) { window.signTask = async function(taskId, userId) {
// Если userId не передан, используем текущего пользователя
const targetUserId = userId || currentUser?.id; const targetUserId = userId || currentUser?.id;
if (!targetUserId) { if (!targetUserId) {
alert('❌ Не удалось определить текущего пользователя'); alert('❌ Не удалось определить текущего пользователя');
return false; return false;
@@ -109,7 +96,6 @@
try { try {
const signers = await getSigners(); const signers = await getSigners();
if (!signers.length) { if (!signers.length) {
alert('❌ Секретари не найдены в системе'); alert('❌ Секретари не найдены в системе');
return false; return false;
@@ -119,11 +105,9 @@
const msg = signers.length === 1 const msg = signers.length === 1
? `✍️ Назначить подписанта?\n\n${names}` ? `✍️ Назначить подписанта?\n\n${names}`
: `✍️ Назначить подписантов?\n\n${names}`; : `✍️ Назначить подписантов?\n\n${names}`;
if (!confirm(msg)) return false; if (!confirm(msg)) return false;
let response; let response;
if (signers.length > 1) { if (signers.length > 1) {
const url = CONFIG.replaceAllEndpoint.replace('${taskId}', taskId); const url = CONFIG.replaceAllEndpoint.replace('${taskId}', taskId);
response = await fetch(url, { response = await fetch(url, {
@@ -145,16 +129,14 @@
if (response.ok) { if (response.ok) {
alert(`✅ Задача ${signers.length > 1 ? 'назначена подписантам' : 'переназначена подписанту'}`); alert(`✅ Задача ${signers.length > 1 ? 'назначена подписантам' : 'переназначена подписанту'}`);
// Пробуем перезагрузить задачи разными способами // Пробуем перезагрузить задачи
if (window.TasksType && typeof window.TasksType.loadTasks === 'function') { if (window.TasksType && typeof window.TasksType.loadTasks === 'function') {
window.TasksType.loadTasks(); window.TasksType.loadTasks();
} else if (window.loadTasks && typeof window.loadTasks === 'function') { } else if (window.loadTasks && typeof window.loadTasks === 'function') {
window.loadTasks(); window.loadTasks();
} else { } else {
// Если нет функций загрузки, просто обновляем страницу
setTimeout(() => window.location.reload(), 1500); setTimeout(() => window.location.reload(), 1500);
} }
return true; return true;
} else { } else {
const err = await response.json(); const err = await response.json();
@@ -168,7 +150,7 @@
} }
}; };
// Обновление статуса задачи // Обновление статуса задачи (может пригодиться)
window.updateTaskStatus = async function(taskId, userId, status) { window.updateTaskStatus = async function(taskId, userId, status) {
try { try {
const response = await fetch(`/api/tasks/${taskId}/status`, { const response = await fetch(`/api/tasks/${taskId}/status`, {
@@ -176,7 +158,6 @@
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId, status }) body: JSON.stringify({ userId, status })
}); });
if (response.ok) { if (response.ok) {
if (window.TasksType && typeof window.TasksType.loadTasks === 'function') { if (window.TasksType && typeof window.TasksType.loadTasks === 'function') {
window.TasksType.loadTasks(); window.TasksType.loadTasks();
@@ -196,142 +177,10 @@
} }
}; };
// Получение типа задачи из элемента карточки // Инициализация: получаем данные текущего пользователя (без добавления кнопок)
function getTaskTypeFromCard(card) {
// Ищем элемент с типом задачи
const typeElement = card.querySelector('.task-type-badge, .task-type');
if (typeElement) {
const classList = typeElement.className;
if (classList.includes('document') || classList.includes('Документ')) {
return 'document';
}
}
// Пробуем найти по тексту
const cardText = card.textContent || '';
if (cardText.includes('Документ') || cardText.includes('document')) {
return 'document';
}
return null;
}
// Функция для добавления кнопок в существующие карточки задач
window.addSignatureButtons = function() {
// Показываем кнопку только если пользователь является подписантом
if (!currentUser || isCurrentUserSigner) return;
document.querySelectorAll('[data-task-id]').forEach(card => {
// Проверяем, есть ли уже кнопка
if (card.querySelector('.signature-btn')) return;
// Проверяем тип задачи - только для документов
const taskType = getTaskTypeFromCard(card);
if (taskType !== CONFIG.taskTypeDocument) return;
const taskId = card.dataset.taskId;
// Ищем контейнер action-buttons
const actionsContainer = card.querySelector('.action-buttons');
if (actionsContainer) {
const btn = document.createElement('button');
btn.className = 'signature-btn action-btn sign-btn';
btn.innerHTML = '✍️ Подписать';
btn.onclick = (e) => {
e.stopPropagation();
window.signTask(taskId, currentUser.id);
};
btn.title = 'Передать подписанту';
actionsContainer.appendChild(btn);
}
});
};
// Наблюдатель за изменениями DOM для динамической добавления кнопок
function observeDOM() {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length) {
window.addSignatureButtons();
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
// Функция для получения отображаемого имени типа задачи
function getTaskTypeDisplayName(type) {
const typeMap = {
'document': 'Документ',
'task': 'Задача',
'bug': 'Ошибка',
'request': 'Заявка'
};
return typeMap[type] || type;
}
// Инициализация при загрузке страницы
async function init() { async function init() {
//console.log('🔄 Signature module initializing...');
// Получаем текущего пользователя и проверяем, является ли он подписантом
await getCurrentUser(); await getCurrentUser();
console.log('✅ Signature module loaded (UI integration removed)');
// Добавляем кнопки на существующие карточки только если пользователь подписант
setTimeout(() => {
if (isCurrentUserSigner) {
window.addSignatureButtons();
}
}, 1000);
// Запускаем наблюдение за DOM
observeDOM();
// Перехватываем функцию рендеринга TasksType если она существует
if (window.TasksType && window.TasksType.renderExpandedContent) {
const originalRender = window.TasksType.renderExpandedContent;
window.TasksType.renderExpandedContent = function(task) {
let html = originalRender ? originalRender(task) : '';
// Добавляем кнопку подписания в развернутое содержимое только для документов и если пользователь подписант
if (currentUser && isCurrentUserSigner && task.task_type === CONFIG.taskTypeDocument) {
// Создаем контейнер action-buttons если его нет
if (!html.includes('action-buttons')) {
const signButton = `
<div class="action-buttons" style="margin-bottom: 10px;">
<button class="action-btn sign-btn" onclick="signTask(${task.id}, ${currentUser.id})" title="Передать подписанту">
✍️ Подписать
</button>
</div>
`;
// Вставляем кнопки после заголовка
html = html.replace('<div class="tasks-type-header">',
'<div class="tasks-type-header">' + signButton);
} else {
// Добавляем кнопку в существующий контейнер
const signButton = `
<button class="action-btn sign-btn" onclick="signTask(${task.id}, ${currentUser.id})" title="Передать подписанту">
✍️ Подписать
</button>
`;
html = html.replace('</div><div class="tasks-type-description">',
signButton + '</div><div class="tasks-type-description">');
}
}
return html;
};
}
////console.log('✅ Signature module loaded. User is signer:', isCurrentUserSigner);
} }
// Запускаем инициализацию после загрузки DOM // Запускаем инициализацию после загрузки DOM