// ========== Confirm Dialog ========== function confirmAction(msg) { return confirm(msg || '确定要执行此操作吗?'); } // ========== Delete with Confirm ========== function deleteItem(url, msg) { if (confirmAction(msg || '确定要删除吗?此操作不可恢复。')) { fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' } }).then(res => res.json()).then(data => { if (data.success) { showToast('操作成功', 'success'); setTimeout(() => location.reload(), 800); } else { showToast(data.message || '操作失败', 'danger'); } }).catch(() => { showToast('网络错误', 'danger'); }); } } // ========== Toast Notification ========== function showToast(message, type) { type = type || 'success'; var toastEl = document.createElement('div'); toastEl.className = 'toast align-items-center text-bg-' + type + ' border-0 show'; toastEl.setAttribute('role', 'alert'); toastEl.style.cssText = 'position:fixed;top:24px;right:24px;z-index:9999;min-width:260px;border-radius:16px;box-shadow:-4px -4px 10px rgba(255,255,255,0.8),4px 4px 10px rgba(163,163,200,0.35);'; toastEl.innerHTML = '
' + message + '
'; document.body.appendChild(toastEl); setTimeout(function() { toastEl.remove(); }, 3000); } // ========== Auto-dismiss alerts ========== document.addEventListener('DOMContentLoaded', function() { var alerts = document.querySelectorAll('.alert:not(.alert-permanent)'); alerts.forEach(function(alert) { setTimeout(function() { var bsAlert = new bootstrap.Alert(alert); bsAlert.close(); }, 3000); }); }); // ========== Sidebar Toggle (mobile) ========== function toggleSidebar() { document.querySelector('.sidebar').classList.toggle('show'); } // ========== Format Number ========== function formatNumber(num) { if (num === null || num === undefined) return '0'; return parseFloat(num).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); } // ========== Form Validation ========== (function() { 'use strict'; var forms = document.querySelectorAll('.needs-validation'); forms.forEach(function(form) { form.addEventListener('submit', function(event) { if (!form.checkValidity()) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }); })(); // ========== Date Range Picker Helper ========== function setQuickDateRange(startInput, endInput, days) { var end = new Date(); var start = new Date(); start.setDate(start.getDate() - days); startInput.value = start.toISOString().split('T')[0]; endInput.value = end.toISOString().split('T')[0]; } // ========== Export Table to CSV ========== function exportTableToCSV(tableId, filename) { var table = document.getElementById(tableId); if (!table) return; var rows = table.querySelectorAll('tr'); var csv = []; rows.forEach(function(row) { var cols = row.querySelectorAll('td, th'); var rowData = []; cols.forEach(function(col) { rowData.push('"' + col.innerText.replace(/"/g, '""') + '"'); }); csv.push(rowData.join(',')); }); var blob = new Blob(['\uFEFF' + csv.join('\n')], { type: 'text/csv;charset=utf-8;' }); var link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename || 'export.csv'; link.click(); }