Секретарь
This commit is contained in:
@@ -127,7 +127,22 @@ async function createTask(event) {
|
|||||||
alert('Выберите хотя бы одного исполнителя');
|
alert('Выберите хотя бы одного исполнителя');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Дополнительная проверка для задач типа "document"
|
||||||
|
if (taskType === 'document' && selectedUsers.length > 0) {
|
||||||
|
// Проверяем, что все выбранные пользователи - секретари
|
||||||
|
for (const userId of selectedUsers) {
|
||||||
|
const groups = await getUserGroups(userId);
|
||||||
|
const hasSecretaryGroup = groups.some(group =>
|
||||||
|
group.name === 'Секретарь' ||
|
||||||
|
(typeof group === 'string' && group.includes('Секретарь'))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!hasSecretaryGroup) {
|
||||||
|
alert('Для задач типа "Согласование документа" можно выбирать только пользователей из группы "Секретарь"');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('title', title);
|
formData.append('title', title);
|
||||||
formData.append('description', description);
|
formData.append('description', description);
|
||||||
|
|||||||
78
public/ui.js
78
public/ui.js
@@ -650,7 +650,7 @@ async function loadTaskFiles(taskId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Функция для выбора типа задачи
|
// Функция для выбора типа задачи
|
||||||
function selectTaskType(type) {
|
async function selectTaskType(type) {
|
||||||
// Убираем активный класс со всех кнопок
|
// Убираем активный класс со всех кнопок
|
||||||
document.querySelectorAll('.task-type-btn').forEach(btn => {
|
document.querySelectorAll('.task-type-btn').forEach(btn => {
|
||||||
btn.classList.remove('active');
|
btn.classList.remove('active');
|
||||||
@@ -666,8 +666,66 @@ function selectTaskType(type) {
|
|||||||
updateTaskFormBasedOnType(type);
|
updateTaskFormBasedOnType(type);
|
||||||
// Предлагаем заголовок по умолчанию
|
// Предлагаем заголовок по умолчанию
|
||||||
suggestDefaultTitle(type);
|
suggestDefaultTitle(type);
|
||||||
}
|
|
||||||
|
|
||||||
|
// Для типа "document" перезагружаем пользователей с фильтрацией
|
||||||
|
if (type === 'document') {
|
||||||
|
await reloadUsersForDocumentType();
|
||||||
|
} else {
|
||||||
|
// Для других типов перезагружаем обычных пользователей
|
||||||
|
await loadUsers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// функция для перезагрузки пользователей для типа "document"
|
||||||
|
async function reloadUsersForDocumentType() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/users');
|
||||||
|
const allUsersData = await response.json();
|
||||||
|
|
||||||
|
// Фильтруем только пользователей из группы "Секретарь"
|
||||||
|
const secretaries = [];
|
||||||
|
for (const user of allUsersData) {
|
||||||
|
if (user.id === currentUser.id) continue;
|
||||||
|
|
||||||
|
const groups = await getUserGroups(user.id);
|
||||||
|
const hasSecretaryGroup = groups.some(group =>
|
||||||
|
group.name === 'Секретарь' ||
|
||||||
|
(typeof group === 'string' && group.includes('Секретарь'))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasSecretaryGroup) {
|
||||||
|
secretaries.push(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
users = secretaries;
|
||||||
|
filteredUsers = [...users];
|
||||||
|
renderUsersChecklist();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка загрузки секретарей:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Используем кэширование, чтобы не делать лишние запросы
|
||||||
|
async function getUserGroups(userId) {
|
||||||
|
// Используем кэширование, чтобы не делать лишние запросы
|
||||||
|
if (!window.userGroupsCache) window.userGroupsCache = {};
|
||||||
|
|
||||||
|
if (window.userGroupsCache[userId]) {
|
||||||
|
return window.userGroupsCache[userId];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api2/idusers/user/${userId}/groups`);
|
||||||
|
if (!response.ok) return [];
|
||||||
|
|
||||||
|
const groups = await response.json();
|
||||||
|
window.userGroupsCache[userId] = groups || [];
|
||||||
|
return window.userGroupsCache[userId];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка получения групп пользователя:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
// Функция для предложения заголовка по умолчанию
|
// Функция для предложения заголовка по умолчанию
|
||||||
function suggestDefaultTitle(type) {
|
function suggestDefaultTitle(type) {
|
||||||
const titleField = document.getElementById('title');
|
const titleField = document.getElementById('title');
|
||||||
@@ -695,6 +753,7 @@ function suggestDefaultTitle(type) {
|
|||||||
// Функция для обновления формы в зависимости от типа задачи
|
// Функция для обновления формы в зависимости от типа задачи
|
||||||
function updateTaskFormBasedOnType(type) {
|
function updateTaskFormBasedOnType(type) {
|
||||||
const userSearchField = document.getElementById('user-search');
|
const userSearchField = document.getElementById('user-search');
|
||||||
|
const taskTypeInfo = document.getElementById('task-type-info');
|
||||||
|
|
||||||
// Устанавливаем заголовки placeholder для поиска исполнителей
|
// Устанавливаем заголовки placeholder для поиска исполнителей
|
||||||
const defaultPlaceholders = {
|
const defaultPlaceholders = {
|
||||||
@@ -713,7 +772,22 @@ function updateTaskFormBasedOnType(type) {
|
|||||||
if (userSearchField) {
|
if (userSearchField) {
|
||||||
userSearchField.placeholder = defaultPlaceholders[type] || 'Поиск исполнителей...';
|
userSearchField.placeholder = defaultPlaceholders[type] || 'Поиск исполнителей...';
|
||||||
}
|
}
|
||||||
|
// Показываем информацию о типе задачи
|
||||||
|
if (taskTypeInfo) {
|
||||||
|
const typeInfo = {
|
||||||
|
'regular': 'Доступны все пользователи в зависимости от ваших прав',
|
||||||
|
'document': 'Доступны только пользователи из группы "Секретарь"',
|
||||||
|
'it': 'Доступны ИТ специалисты',
|
||||||
|
'ahch': 'Доступны сотрудники АХЧ',
|
||||||
|
'psychologist': 'Доступны психологи',
|
||||||
|
'speech_therapist': 'Доступны логопеды',
|
||||||
|
'hr': 'Доступны сотрудники кадровой службы',
|
||||||
|
'certificate': 'Доступны секретари и завучи',
|
||||||
|
'e_journal': 'Доступны администраторы электронного журнала'
|
||||||
|
};
|
||||||
|
|
||||||
|
taskTypeInfo.textContent = typeInfo[type] || '';
|
||||||
|
}
|
||||||
// Показываем/скрываем дополнительные поля в зависимости от типа
|
// Показываем/скрываем дополнительные поля в зависимости от типа
|
||||||
showAdditionalFieldsForType(type);
|
showAdditionalFieldsForType(type);
|
||||||
}
|
}
|
||||||
|
|||||||
240
public/users.js
240
public/users.js
@@ -6,6 +6,9 @@ let selectedUsers = [];
|
|||||||
let editSelectedUsers = [];
|
let editSelectedUsers = [];
|
||||||
let copySelectedUsers = [];
|
let copySelectedUsers = [];
|
||||||
|
|
||||||
|
// Добавьте переменную для хранения групп пользователей
|
||||||
|
let userGroupsCache = {};
|
||||||
|
|
||||||
async function loadUsers() {
|
async function loadUsers() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/users');
|
const response = await fetch('/api/users');
|
||||||
@@ -24,9 +27,49 @@ async function loadUsers() {
|
|||||||
console.error('Ошибка загрузки пользователей:', error);
|
console.error('Ошибка загрузки пользователей:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function filterAssignableUsers(allUsers) {
|
|
||||||
|
// Добавьте функцию для получения групп пользователя
|
||||||
|
async function getUserGroups(userId) {
|
||||||
|
if (userGroupsCache[userId]) {
|
||||||
|
return userGroupsCache[userId];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api2/idusers/user/${userId}/groups`);
|
||||||
|
if (!response.ok) return [];
|
||||||
|
|
||||||
|
const groups = await response.json();
|
||||||
|
userGroupsCache[userId] = groups || [];
|
||||||
|
return userGroupsCache[userId];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка получения групп пользователя:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обновите функцию filterAssignableUsers
|
||||||
|
function filterAssignableUsers(allUsers, taskType = 'regular') {
|
||||||
if (!currentUser) return [];
|
if (!currentUser) return [];
|
||||||
|
|
||||||
|
// Для задач типа "document" - только пользователи из группы "Секретарь"
|
||||||
|
if (taskType === 'document') {
|
||||||
|
return allUsers.filter(async (user) => {
|
||||||
|
if (user.id === currentUser.id) return false;
|
||||||
|
|
||||||
|
// Получаем группы пользователя
|
||||||
|
const groups = await getUserGroups(user.id);
|
||||||
|
|
||||||
|
// Проверяем, есть ли группа "Секретарь"
|
||||||
|
const hasSecretaryGroup = groups.some(group =>
|
||||||
|
group.name === 'Секретарь' ||
|
||||||
|
(typeof group === 'string' && group.includes('Секретарь'))
|
||||||
|
);
|
||||||
|
|
||||||
|
return hasSecretaryGroup;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для других типов задач - обычная фильтрация
|
||||||
// Администратор видит всех пользователей
|
// Администратор видит всех пользователей
|
||||||
if (currentUser.role === 'admin') {
|
if (currentUser.role === 'admin') {
|
||||||
return allUsers.filter(user => user.id !== currentUser.id);
|
return allUsers.filter(user => user.id !== currentUser.id);
|
||||||
@@ -67,77 +110,8 @@ function filterAssignableUsers(allUsers) {
|
|||||||
user.id !== currentUser.id
|
user.id !== currentUser.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Проверяем группы пользователя для определения прав
|
|
||||||
const userGroups = currentUser.groups || [];
|
|
||||||
|
|
||||||
// Загружаем конфигурацию групп из настроек
|
return [];
|
||||||
// (предполагается, что эти переменные определены в глобальной области)
|
|
||||||
const allowedGroups = getGroupsForCurrentUser();
|
|
||||||
|
|
||||||
// Если у пользователя нет специальных групп, возвращаем пустой массив
|
|
||||||
if (allowedGroups.length === 0) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Фильтруем пользователей по группам
|
|
||||||
return allUsers.filter(user => {
|
|
||||||
// Пользователь не может назначать задачи себе
|
|
||||||
if (user.id === currentUser.id) return false;
|
|
||||||
|
|
||||||
// Если у пользователя есть группы, проверяем пересечение
|
|
||||||
if (user.groups && Array.isArray(user.groups)) {
|
|
||||||
return user.groups.some(group => allowedGroups.includes(group));
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Функция для получения групп, которым текущий пользователь может назначать задачи
|
|
||||||
function getGroupsForCurrentUser() {
|
|
||||||
const allowedGroups = [];
|
|
||||||
const userGroups = currentUser.groups || [];
|
|
||||||
|
|
||||||
// Определяем, какие группы доступны для назначения
|
|
||||||
// На основе ролей и групп текущего пользователя
|
|
||||||
|
|
||||||
// Пример: пользователи с ролью 'secretary' могут назначать задачи группам 'teachers'
|
|
||||||
if (currentUser.role === 'secretary') {
|
|
||||||
allowedGroups.push('teachers', 'staff');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пример: пользователи из группы 'department_head' могут назначать своей группе
|
|
||||||
if (userGroups.includes('department_head')) {
|
|
||||||
allowedGroups.push('department_head', 'teachers');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пример: для помощи (help) можно назначать всем
|
|
||||||
if (currentUser.role === 'help') {
|
|
||||||
// Можно указать конкретные группы или 'all' для всех
|
|
||||||
allowedGroups.push('teachers', 'staff', 'administration');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пример: для IT поддержки
|
|
||||||
if (currentUser.role === 'ithelp') {
|
|
||||||
allowedGroups.push('teachers', 'staff', 'administration', 'it_department');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пример: пользователи с ролью 'request' могут создавать заявки для всех
|
|
||||||
if (currentUser.role === 'request') {
|
|
||||||
allowedGroups.push('all'); // Специальное значение "все"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пример: пользователи с ролью 'tasks' (задачи) могут назначать учителям
|
|
||||||
if (currentUser.role === 'tasks') {
|
|
||||||
allowedGroups.push('teachers');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Если массив содержит 'all', возвращаем специальный маркер
|
|
||||||
if (allowedGroups.includes('all')) {
|
|
||||||
return ['all']; // Это будет обрабатываться в фильтрации
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...new Set(allowedGroups)]; // Убираем дубликаты
|
|
||||||
}
|
}
|
||||||
function populateFilterDropdowns() {
|
function populateFilterDropdowns() {
|
||||||
const creatorFilter = document.getElementById('creator-filter');
|
const creatorFilter = document.getElementById('creator-filter');
|
||||||
@@ -157,33 +131,119 @@ function populateFilterDropdowns() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterUsers() {
|
// Обновите функцию filterUsers с учетом типа задачи
|
||||||
|
async function filterUsers() {
|
||||||
const search = document.getElementById('user-search').value.toLowerCase();
|
const search = document.getElementById('user-search').value.toLowerCase();
|
||||||
filteredUsers = users.filter(user =>
|
const taskType = document.getElementById('task-type').value || 'regular';
|
||||||
user.name.toLowerCase().includes(search) ||
|
|
||||||
user.login.toLowerCase().includes(search) ||
|
// Для задач типа "document" нужна особая фильтрация
|
||||||
user.email.toLowerCase().includes(search)
|
if (taskType === 'document') {
|
||||||
);
|
// Сначала фильтруем по поисковому запросу
|
||||||
|
let tempFiltered = users.filter(user =>
|
||||||
|
user.name.toLowerCase().includes(search) ||
|
||||||
|
user.login.toLowerCase().includes(search) ||
|
||||||
|
user.email.toLowerCase().includes(search)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Затем проверяем группы для каждого пользователя
|
||||||
|
filteredUsers = [];
|
||||||
|
for (const user of tempFiltered) {
|
||||||
|
const groups = await getUserGroups(user.id);
|
||||||
|
const hasSecretaryGroup = groups.some(group =>
|
||||||
|
group.name === 'Секретарь' ||
|
||||||
|
(typeof group === 'string' && group.includes('Секретарь'))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasSecretaryGroup) {
|
||||||
|
filteredUsers.push(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Обычная фильтрация для других типов задач
|
||||||
|
filteredUsers = users.filter(user =>
|
||||||
|
user.name.toLowerCase().includes(search) ||
|
||||||
|
user.login.toLowerCase().includes(search) ||
|
||||||
|
user.email.toLowerCase().includes(search)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderUsersChecklist();
|
renderUsersChecklist();
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterEditUsers() {
|
async function filterEditUsers() {
|
||||||
const search = document.getElementById('edit-user-search').value.toLowerCase();
|
const search = document.getElementById('edit-user-search').value.toLowerCase();
|
||||||
const filtered = users.filter(user =>
|
const task = tasks.find(t => t.id === document.getElementById('edit-task-id').value);
|
||||||
user.name.toLowerCase().includes(search) ||
|
const taskType = task ? task.task_type : 'regular';
|
||||||
user.login.toLowerCase().includes(search) ||
|
|
||||||
user.email.toLowerCase().includes(search)
|
let filtered = [];
|
||||||
);
|
|
||||||
|
if (taskType === 'document') {
|
||||||
|
// Для задач типа "document" - только секретари
|
||||||
|
let tempFiltered = users.filter(user =>
|
||||||
|
user.name.toLowerCase().includes(search) ||
|
||||||
|
user.login.toLowerCase().includes(search) ||
|
||||||
|
user.email.toLowerCase().includes(search)
|
||||||
|
);
|
||||||
|
|
||||||
|
filtered = [];
|
||||||
|
for (const user of tempFiltered) {
|
||||||
|
const groups = await getUserGroups(user.id);
|
||||||
|
const hasSecretaryGroup = groups.some(group =>
|
||||||
|
group.name === 'Секретарь' ||
|
||||||
|
(typeof group === 'string' && group.includes('Секретарь'))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasSecretaryGroup) {
|
||||||
|
filtered.push(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filtered = users.filter(user =>
|
||||||
|
user.name.toLowerCase().includes(search) ||
|
||||||
|
user.login.toLowerCase().includes(search) ||
|
||||||
|
user.email.toLowerCase().includes(search)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderEditUsersChecklist(filtered);
|
renderEditUsersChecklist(filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterCopyUsers() {
|
async function filterCopyUsers() {
|
||||||
const search = document.getElementById('copy-user-search').value.toLowerCase();
|
const search = document.getElementById('copy-user-search').value.toLowerCase();
|
||||||
const filtered = users.filter(user =>
|
const taskId = document.getElementById('copy-task-id').value;
|
||||||
user.name.toLowerCase().includes(search) ||
|
const task = tasks.find(t => t.id === taskId);
|
||||||
user.login.toLowerCase().includes(search) ||
|
const taskType = task ? task.task_type : 'regular';
|
||||||
user.email.toLowerCase().includes(search)
|
|
||||||
);
|
let filtered = [];
|
||||||
|
|
||||||
|
if (taskType === 'document') {
|
||||||
|
// Для задач типа "document" - только секретари
|
||||||
|
let tempFiltered = users.filter(user =>
|
||||||
|
user.name.toLowerCase().includes(search) ||
|
||||||
|
user.login.toLowerCase().includes(search) ||
|
||||||
|
user.email.toLowerCase().includes(search)
|
||||||
|
);
|
||||||
|
|
||||||
|
filtered = [];
|
||||||
|
for (const user of tempFiltered) {
|
||||||
|
const groups = await getUserGroups(user.id);
|
||||||
|
const hasSecretaryGroup = groups.some(group =>
|
||||||
|
group.name === 'Секретарь' ||
|
||||||
|
(typeof group === 'string' && group.includes('Секретарь'))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasSecretaryGroup) {
|
||||||
|
filtered.push(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filtered = users.filter(user =>
|
||||||
|
user.name.toLowerCase().includes(search) ||
|
||||||
|
user.login.toLowerCase().includes(search) ||
|
||||||
|
user.email.toLowerCase().includes(search)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderCopyUsersChecklist(filtered);
|
renderCopyUsersChecklist(filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,6 +257,8 @@ function renderUsersChecklist() {
|
|||||||
<input type="checkbox" name="assignedUsers" value="${user.id}"
|
<input type="checkbox" name="assignedUsers" value="${user.id}"
|
||||||
onchange="toggleUserSelection(this, ${user.id})">
|
onchange="toggleUserSelection(this, ${user.id})">
|
||||||
${user.name}
|
${user.name}
|
||||||
|
${document.getElementById('task-type').value === 'document' ?
|
||||||
|
'<small style="color: #666; margin-left: 5px;">(Секретарь)</small>' : ''}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
|
|||||||
Reference in New Issue
Block a user