Router.register('/settings', async () => {
const me = await API.me().catch(()=>({}));
const users = (me && me.role === 'superadmin') ? await API.adminUsers().catch(()=>({list:[]})) : {list:[]};
const userList = (users.list||[]).map(u=>`
${u.username}${u.role}`).join('') || '暂无用户';
const html = `
账户设置
当前用户
${(me && me.username) ? me.username : '未登录'}
${(me && me.role === 'superadmin') ? `
用户管理
修改用户密码
超级管理员工具
清空上传数据
清空扩展采集
数据概览
良/不良统计:加载中
不良明细:加载中
MAC与批次:加载中
发货记录:加载中
设备状态:加载中
人员信息:加载中
质检报告:加载中
生产时间:加载中
` : ''}
`;
setTimeout(() => {
// 头像文件选择预览
const avatarFileInput = document.getElementById('avatar-file');
const previewAvatar = document.getElementById('preview-avatar');
avatarFileInput?.addEventListener('change', (e) => {
const file = e.target.files?.[0];
if (file) {
// 验证文件类型
if (!file.type.startsWith('image/')) {
API.toast('请选择图片文件');
avatarFileInput.value = '';
return;
}
// 验证文件大小(限制2MB)
if (file.size > 2 * 1024 * 1024) {
API.toast('图片大小不能超过2MB');
avatarFileInput.value = '';
return;
}
// 预览图片
const reader = new FileReader();
reader.onload = (e) => {
previewAvatar.src = e.target.result;
};
reader.readAsDataURL(file);
}
});
// 上传头像
const uploadAvatarBtn = document.getElementById('upload-avatar-btn');
uploadAvatarBtn?.addEventListener('click', async () => {
const file = avatarFileInput?.files?.[0];
if (!file) {
return API.toast('请先选择头像图片');
}
uploadAvatarBtn.disabled = true;
try {
const formData = new FormData();
formData.append('avatar', file);
const res = await fetch('/api/user/upload-avatar', {
method: 'POST',
body: formData,
credentials: 'include'
});
const data = await res.json();
if (res.ok && data.ok) {
API.toast('头像上传成功');
// 更新顶部用户头像显示
const avatarImg = document.getElementById('user-avatar-img');
if (avatarImg && data.avatar_url) {
avatarImg.src = data.avatar_url;
}
// 如果有全局更新函数,调用它
if (window.updateUserDisplay) {
const updatedUser = await API.me().catch(() => null);
window.updateUserDisplay(updatedUser);
}
// 清空文件选择
avatarFileInput.value = '';
} else {
API.toast(data.error || '上传失败');
}
} catch(e) {
API.toast('上传失败:' + e.message);
} finally {
uploadAvatarBtn.disabled = false;
}
});
// 恢复默认头像
const resetAvatarBtn = document.getElementById('reset-avatar-btn');
resetAvatarBtn?.addEventListener('click', async () => {
resetAvatarBtn.disabled = true;
try {
const res = await fetch('/api/user/reset-avatar', {
method: 'POST',
credentials: 'include'
});
const data = await res.json();
if (res.ok && data.ok) {
API.toast('已恢复默认头像');
previewAvatar.src = './assets/user-avatar.svg';
const avatarImg = document.getElementById('user-avatar-img');
if (avatarImg) {
avatarImg.src = './assets/user-avatar.svg';
}
if (avatarFileInput) avatarFileInput.value = '';
// 如果有全局更新函数,调用它
if (window.updateUserDisplay) {
const updatedUser = await API.me().catch(() => null);
window.updateUserDisplay(updatedUser);
}
} else {
API.toast(data.error || '操作失败');
}
} catch(e) {
API.toast('操作失败:' + e.message);
} finally {
resetAvatarBtn.disabled = false;
}
});
// 添加新用户
const addUserBtn = document.getElementById('add-user-btn');
addUserBtn?.addEventListener('click', async () => {
const usernameEl = document.getElementById('new-username');
const passwordEl = document.getElementById('new-password');
const roleEl = document.getElementById('new-role');
const username = usernameEl?.value?.trim();
const password = passwordEl?.value;
const role = roleEl?.value || 'admin';
if (!username || !password) {
return API.toast('请输入用户名和密码');
}
if (password.length < 6) {
return API.toast('密码长度至少6位');
}
addUserBtn.disabled = true;
try {
const res = await fetch('/api/admin/add-user', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ username, password, role })
});
const data = await res.json();
if (res.ok && data.ok) {
API.toast(data.message || '用户创建成功');
// 清空输入框
if (usernameEl) usernameEl.value = '';
if (passwordEl) passwordEl.value = '';
// 刷新页面以更新用户列表
setTimeout(() => Router.navigate('/settings'), 1000);
} else {
API.toast(data.error || '创建失败');
}
} catch(e) {
API.toast('创建失败:' + e.message);
} finally {
addUserBtn.disabled = false;
}
});
// 修改密码
const change = document.getElementById('change-btn');
change?.addEventListener('click', async () => {
const uEl = document.getElementById('reset-user');
const pEl = document.getElementById('reset-pass');
const u = uEl ? uEl.value : '';
const p = pEl ? pEl.value : '';
if (!u || !p) return API.toast('请输入用户与新密码');
change.disabled = true;
try {
await API.changePassword(u, p);
API.toast('已修改');
} catch(e) {
API.toast('修改失败');
} finally {
change.disabled = false;
}
});
document.querySelectorAll('button[data-clear]')?.forEach(btn => {
btn.addEventListener('click', async () => {
const mod = btn.getAttribute('data-clear');
btn.disabled = true;
try{
await API.clearModule(mod);
API.toast('已清空');
}catch(e){
API.toast('清空失败');
}finally{
btn.disabled = false;
}
});
});
(async ()=>{
const ov = await API.overview().catch(()=>null);
const setText=(id, text)=>{const el=document.getElementById(id); if(el) el.textContent=text;}
if (ov) {
setText('overview-stats', `良/不良统计:${ov.stats.records} 条(良 ${ov.stats.goodTotal} / 不良 ${ov.stats.badTotal})`);
setText('overview-defects', `不良明细:${ov.defects} 条`);
setText('overview-mac', `MAC与批次:${ov.mac} 条`);
setText('overview-shipments', `发货记录:${ov.shipments.records} 条(总量 ${ov.shipments.qtyTotal})`);
setText('overview-devices', `设备状态:${ov.devices} 条`);
setText('overview-personnel', `人员信息:${ov.personnel} 条`);
setText('overview-qa', `质检报告:${ov.qa} 条`);
setText('overview-production', `生产时间:${ov.production} 条`);
}
})();
}, 0);
return html;
});