Files
sklad_legacy/js/profile.js
cyrteL 13c64c503e Add files via upload
v0.2(css + js)
2025-07-28 14:21:39 +03:00

433 lines
17 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.

// JavaScript для страницы профиля пользователя
class ProfileManager {
constructor() {
this.warehouse = new WarehouseManager();
this.currentUser = null;
this.userOperations = [];
this.init();
}
init() {
$(document).ready(() => {
this.loadProfile();
this.bindEvents();
});
}
bindEvents() {
// Обработчики для настроек
$('#saveSettingsBtn').on('click', () => this.saveSettings());
// Обработчики для форм
$('#changePasswordForm').on('submit', (e) => {
e.preventDefault();
this.savePassword();
});
$('#editProfileForm').on('submit', (e) => {
e.preventDefault();
this.saveProfile();
});
}
// Загрузка профиля
async loadProfile() {
try {
this.currentUser = auth.getCurrentUser();
if (!this.currentUser) {
window.location.href = 'login.html';
return;
}
this.displayUserInfo();
await this.loadUserStatistics();
await this.loadUserOperations();
this.loadSettings();
} catch (error) {
console.error('Ошибка при загрузке профиля:', error);
auth.showNotification('Ошибка при загрузке профиля', 'danger');
}
}
// Отображение информации о пользователе
displayUserInfo() {
// Основная информация
$('#userName').text(this.currentUser.name);
$('#userPosition').text(this.currentUser.position);
$('#userDepartment').text(this.currentUser.department);
$('#userEmail').text(this.currentUser.email);
// Роли
const roles = this.currentUser.roles.map(role => this.getRoleDisplayName(role)).join(', ');
$('#userRoles').html(`<span class="badge bg-primary me-1">${roles}</span>`);
// Разрешения
const permissions = this.currentUser.permissions.map(perm => this.getPermissionDisplayName(perm)).join(', ');
$('#userPermissions').html(`<span class="badge bg-secondary me-1">${permissions}</span>`);
// Дата регистрации (имитация)
const registrationDate = new Date();
registrationDate.setMonth(registrationDate.getMonth() - 3); // 3 месяца назад
$('#userRegistrationDate').text(registrationDate.toLocaleDateString('ru-RU'));
// Последний вход
const lastLogin = new Date();
lastLogin.setHours(lastLogin.getHours() - 2); // 2 часа назад
$('#lastLogin').text(lastLogin.toLocaleDateString('ru-RU') + ' ' + lastLogin.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }));
}
// Получение отображаемого названия роли
getRoleDisplayName(role) {
const roleNames = {
'admin': 'Администратор',
'manager': 'Менеджер',
'operator': 'Оператор',
'viewer': 'Наблюдатель'
};
return roleNames[role] || role;
}
// Получение отображаемого названия разрешения
getPermissionDisplayName(permission) {
const permissionNames = {
'read': 'Чтение',
'write': 'Запись',
'delete': 'Удаление',
'admin': 'Администрирование'
};
return permissionNames[permission] || permission;
}
// Загрузка статистики пользователя
async loadUserStatistics() {
try {
const operations = await this.warehouse.getOperations();
const userOperations = operations.filter(op => op.employeeId === this.currentUser.id);
// Общее количество операций
$('#totalOperations').text(userOperations.length);
// Операции в этом месяце
const thisMonth = new Date().getMonth();
const thisYear = new Date().getFullYear();
const thisMonthOperations = userOperations.filter(op => {
const opDate = new Date(op.date);
return opDate.getMonth() === thisMonth && opDate.getFullYear() === thisYear;
});
$('#thisMonthOperations').text(thisMonthOperations.length);
// Операции сегодня
const today = new Date().toISOString().split('T')[0];
const todayOperations = userOperations.filter(op => op.date.startsWith(today));
$('#todayOperations').text(todayOperations.length);
} catch (error) {
console.error('Ошибка при загрузке статистики:', error);
}
}
// Загрузка операций пользователя
async loadUserOperations() {
try {
const operations = await this.warehouse.getOperations();
this.userOperations = operations
.filter(op => op.employeeId === this.currentUser.id)
.sort((a, b) => new Date(b.date) - new Date(a.date))
.slice(0, 10); // Последние 10 операций
this.renderUserOperations();
} catch (error) {
console.error('Ошибка при загрузке операций:', error);
}
}
// Рендеринг операций пользователя
renderUserOperations() {
const tbody = $('#userOperationsTable tbody');
tbody.empty();
if (this.userOperations.length === 0) {
tbody.html(`
<tr>
<td colspan="5" class="text-center text-muted py-4">
<i class="fas fa-inbox fa-2x mb-3"></i>
<br>У вас пока нет операций
</td>
</tr>
`);
return;
}
this.userOperations.forEach(operation => {
const row = this.createOperationRow(operation);
tbody.append(row);
});
}
// Создание строки операции
createOperationRow(operation) {
const typeIcon = operation.type === 'incoming' ? 'fa-box-open text-success' : 'fa-truck text-warning';
const typeText = operation.type === 'incoming' ? 'Приход' : 'Расход';
const statusClass = this.getStatusClass(operation.status);
const statusText = this.getStatusText(operation.status);
return `
<tr>
<td>${this.formatDate(operation.date)}</td>
<td>
<i class="fas ${typeIcon} me-1"></i>
${typeText}
</td>
<td>${operation.itemName}</td>
<td>${operation.quantity}</td>
<td>
<span class="status-badge ${statusClass}">${statusText}</span>
</td>
</tr>
`;
}
// Получение класса статуса
getStatusClass(status) {
switch (status) {
case 'completed': return 'status-completed';
case 'pending': return 'status-pending';
case 'cancelled': return 'status-cancelled';
default: return 'status-pending';
}
}
// Получение текста статуса
getStatusText(status) {
switch (status) {
case 'completed': return 'Завершено';
case 'pending': return 'В обработке';
case 'cancelled': return 'Отменено';
default: return 'Неизвестно';
}
}
// Форматирование даты
formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString('ru-RU', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
// Загрузка настроек
loadSettings() {
// Загружаем настройки из localStorage
const settings = JSON.parse(localStorage.getItem('user_settings') || '{}');
$('#emailNotifications').prop('checked', settings.emailNotifications !== false);
$('#lowStockAlerts').prop('checked', settings.lowStockAlerts !== false);
$('#operationReports').prop('checked', settings.operationReports || false);
$('#themeSelect').val(settings.theme || 'light');
$('#languageSelect').val(settings.language || 'ru');
}
// Сохранение настроек
saveSettings() {
const settings = {
emailNotifications: $('#emailNotifications').is(':checked'),
lowStockAlerts: $('#lowStockAlerts').is(':checked'),
operationReports: $('#operationReports').is(':checked'),
theme: $('#themeSelect').val(),
language: $('#languageSelect').val()
};
localStorage.setItem('user_settings', JSON.stringify(settings));
auth.showNotification('Настройки сохранены', 'success');
}
// Смена пароля
changePassword() {
$('#changePasswordForm')[0].reset();
$('#changePasswordModal').modal('show');
}
// Сохранение пароля
savePassword() {
const currentPassword = $('#currentPassword').val();
const newPassword = $('#newPassword').val();
const confirmPassword = $('#confirmPassword').val();
// Валидация
if (!currentPassword || !newPassword || !confirmPassword) {
auth.showNotification('Пожалуйста, заполните все поля', 'warning');
return;
}
if (newPassword !== confirmPassword) {
auth.showNotification('Новые пароли не совпадают', 'warning');
return;
}
if (newPassword.length < 6) {
auth.showNotification('Новый пароль должен содержать минимум 6 символов', 'warning');
return;
}
// В реальном приложении здесь был бы запрос к серверу
// Для демонстрации просто показываем уведомление
auth.showNotification('Пароль успешно изменен', 'success');
$('#changePasswordModal').modal('hide');
$('#changePasswordForm')[0].reset();
}
// Редактирование профиля
editProfile() {
// Заполняем форму текущими данными
$('#editName').val(this.currentUser.name);
$('#editEmail').val(this.currentUser.email);
$('#editDepartment').val(this.currentUser.department);
$('#editPosition').val(this.currentUser.position);
$('#editPhone').val(this.currentUser.phone || '');
$('#editProfileModal').modal('show');
}
// Сохранение профиля
saveProfile() {
const formData = {
name: $('#editName').val(),
email: $('#editEmail').val(),
department: $('#editDepartment').val(),
position: $('#editPosition').val(),
phone: $('#editPhone').val()
};
// Валидация
if (!formData.name || !formData.email) {
auth.showNotification('Пожалуйста, заполните обязательные поля', 'warning');
return;
}
if (!this.isValidEmail(formData.email)) {
auth.showNotification('Пожалуйста, введите корректный email', 'warning');
return;
}
// В реальном приложении здесь был бы запрос к серверу
// Для демонстрации обновляем локальные данные
Object.assign(this.currentUser, formData);
localStorage.setItem('warehouse_user', JSON.stringify(this.currentUser));
// Обновляем отображение
this.displayUserInfo();
auth.showNotification('Профиль успешно обновлен', 'success');
$('#editProfileModal').modal('hide');
}
// Просмотр активности
viewActivity() {
// В реальном приложении здесь можно открыть страницу с детальной статистикой
auth.showNotification('Функция просмотра активности находится в разработке', 'info');
}
// Валидация email
isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
// Получение статистики активности
getActivityStats() {
const now = new Date();
const stats = {
today: 0,
thisWeek: 0,
thisMonth: 0,
total: this.userOperations.length
};
this.userOperations.forEach(operation => {
const opDate = new Date(operation.date);
const diffTime = now - opDate;
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
if (diffDays === 0) stats.today++;
if (diffDays <= 7) stats.thisWeek++;
if (diffDays <= 30) stats.thisMonth++;
});
return stats;
}
// Экспорт данных пользователя
exportUserData() {
try {
const userData = {
profile: this.currentUser,
operations: this.userOperations,
statistics: this.getActivityStats(),
settings: JSON.parse(localStorage.getItem('user_settings') || '{}')
};
const dataStr = JSON.stringify(userData, null, 2);
const blob = new Blob([dataStr], { type: 'application/json' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', `profile_${this.currentUser.username}_${new Date().toISOString().split('T')[0]}.json`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
auth.showNotification('Данные профиля экспортированы', 'success');
} catch (error) {
console.error('Ошибка при экспорте:', error);
auth.showNotification('Ошибка при экспорте данных', 'danger');
}
}
// Получение рекомендаций
getRecommendations() {
const recommendations = [];
// Рекомендации на основе роли
if (this.currentUser.roles.includes('admin')) {
recommendations.push({
type: 'info',
title: 'Административные функции',
message: 'У вас есть доступ ко всем функциям системы. Не забудьте регулярно проверять отчеты и управлять пользователями.'
});
}
if (this.currentUser.roles.includes('manager')) {
recommendations.push({
type: 'warning',
title: 'Управление складом',
message: 'Следите за товарами с низким запасом и контролируйте операции операторов.'
});
}
// Рекомендации на основе активности
const stats = this.getActivityStats();
if (stats.today === 0) {
recommendations.push({
type: 'success',
title: 'Добро пожаловать!',
message: 'Сегодня у вас пока нет операций. Начните работу с добавления товаров или оформления операций.'
});
}
return recommendations;
}
}
// Инициализация менеджера профиля
const profileManager = new ProfileManager();