383 lines
12 KiB
JavaScript
383 lines
12 KiB
JavaScript
|
|
// 企业设置管理系统 - 主要JavaScript文件
|
|||
|
|
// 包含所有核心功能和交互逻辑
|
|||
|
|
|
|||
|
|
class EnterpriseSettingsApp {
|
|||
|
|
constructor() {
|
|||
|
|
this.currentUser = null;
|
|||
|
|
this.settings = {};
|
|||
|
|
this.init();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
init() {
|
|||
|
|
this.checkAuthentication();
|
|||
|
|
this.initializeDefaultSettings();
|
|||
|
|
this.bindGlobalEvents();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 身份验证管理
|
|||
|
|
checkAuthentication() {
|
|||
|
|
const loginData = localStorage.getItem('companyLogin') || sessionStorage.getItem('companyLogin');
|
|||
|
|
if (loginData) {
|
|||
|
|
this.currentUser = JSON.parse(loginData);
|
|||
|
|
} else if (window.location.pathname.includes('settings.html')) {
|
|||
|
|
window.location.href = 'login.html';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 初始化默认设置
|
|||
|
|
initializeDefaultSettings() {
|
|||
|
|
const defaultSettings = {
|
|||
|
|
noParking: false,
|
|||
|
|
noTraffic: false,
|
|||
|
|
dangerSource: false,
|
|||
|
|
parkingCapacity: 50,
|
|||
|
|
trafficCapacity: 100,
|
|||
|
|
speedLimit: 60,
|
|||
|
|
companyProducts: '我们专注于提供高质量的企业管理解决方案,包括智能交通管理系统、企业资源规划系统、安全监控系统等。致力于为各类企业提供全方位的数字化转型服务。'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const savedSettings = localStorage.getItem('companySettings');
|
|||
|
|
this.settings = savedSettings ? { ...defaultSettings, ...JSON.parse(savedSettings) } : defaultSettings;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 绑定全局事件
|
|||
|
|
bindGlobalEvents() {
|
|||
|
|
// 页面可见性变化
|
|||
|
|
document.addEventListener('visibilitychange', () => {
|
|||
|
|
if (document.hidden) {
|
|||
|
|
this.onPageHidden();
|
|||
|
|
} else {
|
|||
|
|
this.onPageVisible();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 窗口大小变化
|
|||
|
|
window.addEventListener('resize', this.debounce(() => {
|
|||
|
|
this.onWindowResize();
|
|||
|
|
}, 250));
|
|||
|
|
|
|||
|
|
// 键盘快捷键
|
|||
|
|
document.addEventListener('keydown', (e) => {
|
|||
|
|
this.handleKeyboardShortcuts(e);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 页面隐藏时的处理
|
|||
|
|
onPageHidden() {
|
|||
|
|
// 保存当前状态
|
|||
|
|
if (Object.keys(this.settings).length > 0) {
|
|||
|
|
localStorage.setItem('companySettings', JSON.stringify(this.settings));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 页面显示时的处理
|
|||
|
|
onPageVisible() {
|
|||
|
|
// 检查会话状态
|
|||
|
|
this.checkAuthentication();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 窗口大小变化处理
|
|||
|
|
onWindowResize() {
|
|||
|
|
// 响应式布局调整
|
|||
|
|
const isMobile = window.innerWidth < 768;
|
|||
|
|
document.body.classList.toggle('mobile', isMobile);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 键盘快捷键处理
|
|||
|
|
handleKeyboardShortcuts(e) {
|
|||
|
|
// Ctrl/Cmd + S: 保存设置
|
|||
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
|||
|
|
e.preventDefault();
|
|||
|
|
this.saveSettings();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Ctrl/Cmd + R: 重置设置
|
|||
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 'r') {
|
|||
|
|
e.preventDefault();
|
|||
|
|
this.resetSettings();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Escape: 退出当前操作
|
|||
|
|
if (e.key === 'Escape') {
|
|||
|
|
this.exitCurrentOperation();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 防抖函数
|
|||
|
|
debounce(func, wait) {
|
|||
|
|
let timeout;
|
|||
|
|
return function executedFunction(...args) {
|
|||
|
|
const later = () => {
|
|||
|
|
clearTimeout(timeout);
|
|||
|
|
func(...args);
|
|||
|
|
};
|
|||
|
|
clearTimeout(timeout);
|
|||
|
|
timeout = setTimeout(later, wait);
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 节流函数
|
|||
|
|
throttle(func, limit) {
|
|||
|
|
let inThrottle;
|
|||
|
|
return function() {
|
|||
|
|
const args = arguments;
|
|||
|
|
const context = this;
|
|||
|
|
if (!inThrottle) {
|
|||
|
|
func.apply(context, args);
|
|||
|
|
inThrottle = true;
|
|||
|
|
setTimeout(() => inThrottle = false, limit);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置管理
|
|||
|
|
saveSettings() {
|
|||
|
|
localStorage.setItem('companySettings', JSON.stringify(this.settings));
|
|||
|
|
this.showNotification('设置已保存', 'success');
|
|||
|
|
this.logActivity('设置保存', '用户保存了企业设置');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resetSettings() {
|
|||
|
|
if (confirm('确定要重置所有设置为默认值吗?此操作不可撤销。')) {
|
|||
|
|
localStorage.removeItem('companySettings');
|
|||
|
|
this.initializeDefaultSettings();
|
|||
|
|
this.updateAllUI();
|
|||
|
|
this.showNotification('设置已重置为默认值', 'info');
|
|||
|
|
this.logActivity('设置重置', '用户重置了所有企业设置');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 退出当前操作
|
|||
|
|
exitCurrentOperation() {
|
|||
|
|
// 关闭所有模态框
|
|||
|
|
document.querySelectorAll('.modal, .toast').forEach(element => {
|
|||
|
|
element.classList.remove('show', 'active');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 清除焦点
|
|||
|
|
document.activeElement.blur();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新所有UI元素
|
|||
|
|
updateAllUI() {
|
|||
|
|
// 更新开关状态
|
|||
|
|
Object.keys(this.settings).forEach(key => {
|
|||
|
|
const element = document.getElementById(key);
|
|||
|
|
if (element) {
|
|||
|
|
if (element.type === 'checkbox') {
|
|||
|
|
element.checked = this.settings[key];
|
|||
|
|
} else if (element.type === 'range' || element.type === 'number') {
|
|||
|
|
element.value = this.settings[key];
|
|||
|
|
} else {
|
|||
|
|
element.value = this.settings[key];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 更新显示值
|
|||
|
|
this.updateDisplayValues();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新显示值
|
|||
|
|
updateDisplayValues() {
|
|||
|
|
const displays = {
|
|||
|
|
parkingCapacityValue: `${this.settings.parkingCapacity} 辆`,
|
|||
|
|
trafficCapacityValue: `${this.settings.trafficCapacity} 辆`,
|
|||
|
|
speedLimitValue: `${this.settings.speedLimit}`,
|
|||
|
|
charCount: `${this.settings.companyProducts.length} 字符`
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
Object.keys(displays).forEach(id => {
|
|||
|
|
const element = document.getElementById(id);
|
|||
|
|
if (element) {
|
|||
|
|
element.textContent = displays[id];
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 通知系统
|
|||
|
|
showNotification(message, type = 'info', duration = 3000) {
|
|||
|
|
const notification = this.createNotification(message, type);
|
|||
|
|
document.body.appendChild(notification);
|
|||
|
|
|
|||
|
|
// 显示动画
|
|||
|
|
setTimeout(() => {
|
|||
|
|
notification.classList.add('show');
|
|||
|
|
}, 10);
|
|||
|
|
|
|||
|
|
// 自动隐藏
|
|||
|
|
setTimeout(() => {
|
|||
|
|
notification.classList.remove('show');
|
|||
|
|
setTimeout(() => {
|
|||
|
|
document.body.removeChild(notification);
|
|||
|
|
}, 300);
|
|||
|
|
}, duration);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
createNotification(message, type) {
|
|||
|
|
const notification = document.createElement('div');
|
|||
|
|
notification.className = `notification notification-${type}`;
|
|||
|
|
|
|||
|
|
const icons = {
|
|||
|
|
success: '✓',
|
|||
|
|
error: '✕',
|
|||
|
|
warning: '⚠',
|
|||
|
|
info: 'ℹ'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const colors = {
|
|||
|
|
success: 'bg-green-500',
|
|||
|
|
error: 'bg-red-500',
|
|||
|
|
warning: 'bg-yellow-500',
|
|||
|
|
info: 'bg-blue-500'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
notification.innerHTML = `
|
|||
|
|
<div class="flex items-center space-x-3 p-4 bg-white rounded-lg shadow-lg">
|
|||
|
|
<div class="w-8 h-8 ${colors[type]} rounded-full flex items-center justify-center text-white font-bold">
|
|||
|
|
${icons[type]}
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<p class="font-medium text-gray-800">${message}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
`;
|
|||
|
|
|
|||
|
|
return notification;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 活动日志
|
|||
|
|
logActivity(action, description) {
|
|||
|
|
const activity = {
|
|||
|
|
timestamp: new Date().toISOString(),
|
|||
|
|
action,
|
|||
|
|
description,
|
|||
|
|
user: this.currentUser?.companyId || '未知用户'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const activities = JSON.parse(localStorage.getItem('activityLog') || '[]');
|
|||
|
|
activities.unshift(activity);
|
|||
|
|
|
|||
|
|
// 保留最近100条记录
|
|||
|
|
if (activities.length > 100) {
|
|||
|
|
activities.splice(100);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
localStorage.setItem('activityLog', JSON.stringify(activities));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取活动日志
|
|||
|
|
getActivityLog(limit = 10) {
|
|||
|
|
const activities = JSON.parse(localStorage.getItem('activityLog') || '[]');
|
|||
|
|
return activities.slice(0, limit);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 数据验证
|
|||
|
|
validateSettings() {
|
|||
|
|
const errors = [];
|
|||
|
|
|
|||
|
|
if (this.settings.parkingCapacity < 0 || this.settings.parkingCapacity > 1000) {
|
|||
|
|
errors.push('停车容量必须在0-1000之间');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (this.settings.trafficCapacity < 0 || this.settings.trafficCapacity > 1000) {
|
|||
|
|
errors.push('通行容量必须在0-1000之间');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (this.settings.speedLimit < 10 || this.settings.speedLimit > 120) {
|
|||
|
|
errors.push('限速必须在10-120 km/h之间');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return errors;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 导出设置
|
|||
|
|
exportSettings() {
|
|||
|
|
const data = {
|
|||
|
|
settings: this.settings,
|
|||
|
|
exportTime: new Date().toISOString(),
|
|||
|
|
version: '1.0'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
|
|||
|
|
const url = URL.createObjectURL(blob);
|
|||
|
|
|
|||
|
|
const a = document.createElement('a');
|
|||
|
|
a.href = url;
|
|||
|
|
a.download = `enterprise-settings-${new Date().toISOString().split('T')[0]}.json`;
|
|||
|
|
document.body.appendChild(a);
|
|||
|
|
a.click();
|
|||
|
|
document.body.removeChild(a);
|
|||
|
|
|
|||
|
|
URL.revokeObjectURL(url);
|
|||
|
|
this.logActivity('设置导出', '用户导出了企业设置');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 导入设置
|
|||
|
|
importSettings(file) {
|
|||
|
|
const reader = new FileReader();
|
|||
|
|
reader.onload = (e) => {
|
|||
|
|
try {
|
|||
|
|
const data = JSON.parse(e.target.result);
|
|||
|
|
if (data.settings) {
|
|||
|
|
this.settings = { ...this.settings, ...data.settings };
|
|||
|
|
this.updateAllUI();
|
|||
|
|
this.saveSettings();
|
|||
|
|
this.showNotification('设置导入成功', 'success');
|
|||
|
|
this.logActivity('设置导入', '用户导入了企业设置');
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
this.showNotification('设置文件格式错误', 'error');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
reader.readAsText(file);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取系统状态
|
|||
|
|
getSystemStatus() {
|
|||
|
|
return {
|
|||
|
|
authenticated: !!this.currentUser,
|
|||
|
|
settingsCount: Object.keys(this.settings).length,
|
|||
|
|
lastActivity: this.getActivityLog(1)[0]?.timestamp || null,
|
|||
|
|
storageUsed: this.getStorageInfo()
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取存储信息
|
|||
|
|
getStorageInfo() {
|
|||
|
|
let total = 0;
|
|||
|
|
for (let key in localStorage) {
|
|||
|
|
if (localStorage.hasOwnProperty(key)) {
|
|||
|
|
total += localStorage[key].length;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return {
|
|||
|
|
used: total,
|
|||
|
|
available: 5 * 1024 * 1024, // 5MB
|
|||
|
|
percent: (total / (5 * 1024 * 1024)) * 100
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 全局实例
|
|||
|
|
let app;
|
|||
|
|
|
|||
|
|
// 页面加载完成后初始化
|
|||
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|||
|
|
app = new EnterpriseSettingsApp();
|
|||
|
|
|
|||
|
|
// 添加全局错误处理
|
|||
|
|
window.addEventListener('error', function(e) {
|
|||
|
|
console.error('应用错误:', e.error);
|
|||
|
|
app.showNotification('应用出现错误,请刷新页面', 'error');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 添加未处理的Promise错误
|
|||
|
|
window.addEventListener('unhandledrejection', function(e) {
|
|||
|
|
console.error('未处理的Promise错误:', e.reason);
|
|||
|
|
app.showNotification('网络请求失败,请检查网络连接', 'error');
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 导出到全局作用域
|
|||
|
|
window.EnterpriseSettingsApp = EnterpriseSettingsApp;
|