Initial commit

This commit is contained in:
user9994793890
2026-05-29 10:28:07 +08:00
commit ee860ce0ae
87 changed files with 12595 additions and 0 deletions

104
xuexiao/static/js/main.js Normal file
View File

@@ -0,0 +1,104 @@
// ========== 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 = '<div class="d-flex"><div class="toast-body">' + message + '</div><button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button></div>';
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();
}