/
danshine
/
project_1C
Обзор
Документация
Войти
/
danshine
/
project_1C
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
script.js
305 строк
11 KB
danshine
create: index.html, script.js, styles.css
15 май 2026, 09:30
Верифицирован
15 май 2026, 09:30
25ac485
Код
Авторство
О чём код?
// --- DATA LAYER --- let requests = []; let warranties = []; let currentSort = { key: null, asc: true }; // Load from localStorage or default function loadData() { const storedRequests = localStorage.getItem('service_requests'); const storedWarranties = localStorage.getItem('service_warranties'); if (storedRequests) { requests = JSON.parse(storedRequests); } else { // Default data from screenshots requests = [ { id: 'REQ-1042', equipment: 'Ноутбук Dell XPS 15', problem: 'Не включается экран', status: 'new', date: '2023-10-25', client: '' }, { id: 'REQ-1043', equipment: 'МФУ HP LaserJet Pro', problem: 'Замятие бумаги после 2 страниц', status: 'progress', date: '2023-10-24', client: '' }, { id: 'REQ-1044', equipment: 'Смартфон Samsung S22', problem: 'Замена АКБ', status: 'done', date: '2023-10-22', client: '' }, { id: 'REQ-1045', equipment: 'Сервер HP ProLiant', problem: 'Ошибка RAID контроллера', status: 'new', date: '2023-10-26', client: '' } ]; } if (storedWarranties) { warranties = JSON.parse(storedWarranties); } else { warranties = [ { sn: 'SN-99022111', equipment: 'Сервер HP ProLiant DL380', client: 'ООО "Техника+"', status: 'valid', date: '2025-07-15' }, { sn: 'SN-44566777', equipment: 'Ноутбук Dell XPS 15', client: 'ООО "Альфа"', status: 'warning', date: '2023-11-01' }, { sn: 'SN-11223344', equipment: 'МФУ HP LaserJet Pro', client: 'ИП Смирнов', status: 'expired', date: '2020-09-30' } ]; } saveData(); } function saveData() { localStorage.setItem('service_requests', JSON.stringify(requests)); localStorage.setItem('service_warranties', JSON.stringify(warranties)); } // --- HELPER FUNCTIONS --- function getStatusBadge(status) { const map = { 'new': '<span class="status-badge status-new">Новая</span>', 'progress': '<span class="status-badge status-progress">В работе</span>', 'done': '<span class="status-badge status-done">Завершена</span>', 'valid': '<span class="status-badge status-valid"><i class="fa-regular fa-circle-check"></i> Действует</span>', 'warning': '<span class="status-badge status-warning"><i class="fa-regular fa-clock"></i> До завершения 30 дней</span>', 'expired': '<span class="status-badge status-expired">Истекла</span>' }; return map[status] || status; } // Generate next ID function generateId() { const nums = requests.map(r => parseInt(r.id.replace('REQ-', ''))); const max = nums.length ? Math.max(...nums) : 1041; return 'REQ-' + (max + 1); } // --- RENDER FUNCTIONS --- function renderRequestsTable(tbodyId, data) { const tbody = document.getElementById(tbodyId); tbody.innerHTML = ''; data.forEach(item => { const tr = document.createElement('tr'); tr.innerHTML = ` <td>${item.id}</td> <td>${item.equipment}</td> <td>${item.problem}</td> <td> <div class="status-badge ${getStatusClass(item.status)}" onclick="changeStatus('${item.id}', prompt('Новый статус (new/progress/done):'))"> ${getStatusLabel(item.status)} </div> </td> <td>${item.date}</td> <td> <div class="action-cell"> <i class="fa-solid fa-pen-to-square" onclick="editRequest('${item.id}')"></i> <i class="fa-solid fa-trash-can delete-btn" onclick="deleteRequest('${item.id}')"></i> </div> </td> `; tbody.appendChild(tr); }); } function getStatusClass(status) { return 'status-' + status; } function getStatusLabel(status) { const map = { 'new': 'Новая', 'progress': 'В работе', 'done': 'Завершена' }; return map[status] || status; } function renderWarrantyTable(data) { const tbody = document.getElementById('warranty-table-body'); tbody.innerHTML = ''; data.forEach(item => { const tr = document.createElement('tr'); tr.innerHTML = ` <td>${item.sn}</td> <td>${item.equipment}</td> <td>${item.client}</td> <td>${getStatusBadge(item.status)}</td> <td>${item.date}</td> `; tbody.appendChild(tr); }); } function updateStats() { const newCount = requests.filter(r => r.status === 'new').length; const progressCount = requests.filter(r => r.status === 'progress').length; const doneCount = requests.filter(r => r.status === 'done').length; const expiringCount = warranties.filter(w => w.status === 'warning' || w.status === 'expired').length; document.getElementById('stat-new').textContent = newCount; document.getElementById('stat-progress').textContent = progressCount; document.getElementById('stat-done').textContent = doneCount; document.getElementById('stat-warranty-expiring').textContent = expiringCount; } // --- FILTERING & SORTING --- function getFilteredRequests() { const search = document.getElementById('search-input').value.toLowerCase(); const statusFilter = document.getElementById('status-filter').value; return requests.filter(r => { const matchesSearch = r.id.toLowerCase().includes(search) || r.equipment.toLowerCase().includes(search) || r.problem.toLowerCase().includes(search) || r.client.toLowerCase().includes(search); const matchesStatus = statusFilter === 'all' || r.status === statusFilter; return matchesSearch && matchesStatus; }); } function getFilteredWarranties() { const search = document.getElementById('warranty-search').value.toLowerCase(); return warranties.filter(w => w.sn.toLowerCase().includes(search) || w.equipment.toLowerCase().includes(search) || w.client.toLowerCase().includes(search) ); } function sortData(data, key) { if (!key) return data; const sorted = [...data]; sorted.sort((a, b) => { let valA = a[key] || ''; let valB = b[key] || ''; if (valA < valB) return currentSort.asc ? -1 : 1; if (valA > valB) return currentSort.asc ? 1 : -1; return 0; }); return sorted; } // --- ACTIONS --- function changeStatus(id, newStatus) { if (!newStatus) return; const valid = ['new', 'progress', 'done']; if (!valid.includes(newStatus)) { alert('Допустимые статусы: new, progress, done'); return; } const index = requests.findIndex(r => r.id === id); if (index !== -1) { requests[index].status = newStatus; saveData(); refreshAll(); } } function deleteRequest(id) { if (!confirm('Вы уверены, что хотите удалить заявку ' + id + '?')) { return; } const index = requests.findIndex(r => r.id === id); if (index !== -1) { requests.splice(index, 1); saveData(); refreshAll(); } } function editRequest(id) { // Просто переключает статус для демонстрации, можно расширить const request = requests.find(r => r.id === id); if (request) { const newStatus = prompt('Редактирование заявки ' + id + '\nВведите новый статус (new/progress/done):', request.status); if (newStatus) { changeStatus(id, newStatus); } } } function createRequest() { const equipment = document.getElementById('modal-equipment').value; const problem = document.getElementById('modal-problem').value; const client = document.getElementById('modal-client').value; if (!equipment || !problem) { alert('Заполните оборудование и проблему'); return; } const newRequest = { id: generateId(), equipment: equipment, problem: problem, status: 'new', date: new Date().toISOString().slice(0, 10), client: client || '' }; requests.unshift(newRequest); saveData(); closeCreateModal(); refreshAll(); } function refreshAll() { // Dashboard const dashData = sortData(requests.slice(0, 3), 'date'); renderRequestsTable('dashboard-table-body', dashData); // Requests const filtered = getFilteredRequests(); const sorted = sortData(filtered, currentSort.key); renderRequestsTable('requests-table-body', sorted); // Warranty const filteredW = getFilteredWarranties(); const sortedW = sortData(filteredW, currentSort.key); renderWarrantyTable(sortedW); updateStats(); } // --- MODAL --- function openCreateModal() { document.getElementById('create-modal').classList.add('open'); document.getElementById('modal-equipment').value = ''; document.getElementById('modal-problem').value = ''; document.getElementById('modal-client').value = ''; } function closeCreateModal() { document.getElementById('create-modal').classList.remove('open'); } // --- NAVIGATION --- function switchTab(tabName) { document.querySelectorAll('.sidebar nav ul li').forEach(i => i.classList.remove('active')); document.querySelector(`[data-tab="${tabName}"]`).classList.add('active'); document.querySelectorAll('.section').forEach(s => s.classList.remove('active')); document.getElementById(tabName + '-section').classList.add('active'); const titles = { dashboard: 'Обзор сервисного центра', requests: 'Заявки на сервис', warranty: 'Учет гарантий' }; document.getElementById('page-title').textContent = titles[tabName]; } // --- EVENT LISTENERS --- document.addEventListener('DOMContentLoaded', () => { loadData(); refreshAll(); // Sidebar navigation document.querySelectorAll('.sidebar nav ul li').forEach(item => { item.addEventListener('click', function() { switchTab(this.dataset.tab); }); }); // Filters document.getElementById('search-input').addEventListener('input', refreshAll); document.getElementById('status-filter').addEventListener('change', refreshAll); document.getElementById('warranty-search').addEventListener('input', refreshAll); // Sorting document.querySelectorAll('.sortable').forEach(th => { th.addEventListener('click', function() { const key = this.dataset.sort; if (currentSort.key === key) { currentSort.asc = !currentSort.asc; } else { currentSort.key = key; currentSort.asc = true; } refreshAll(); }); }); // Modal close on outside click document.getElementById('create-modal').addEventListener('click', function(e) { if (e.target === this) closeCreateModal(); }); });