// API基础URL const API_BASE_URL = 'http://localhost:8001'; // 全局状态 let currentUser = null; let accessToken = localStorage.getItem('accessToken'); let lastApiCalls = {}; // 记录上次API调用时间,防止重复请求 // DOM元素 const navMenu = document.getElementById('navMenu'); const userInfo = document.getElementById('userInfo'); const loginBtn = document.getElementById('loginBtn'); const registerBtn = document.getElementById('registerBtn'); const logoutBtn = document.getElementById('logoutBtn'); const loginSection = document.getElementById('loginSection'); const registerSection = document.getElementById('registerSection'); const mainSection = document.getElementById('mainSection'); const loginForm = document.getElementById('loginForm'); const registerForm = document.getElementById('registerForm'); const editProfileForm = document.getElementById('editProfileForm'); const createDocForm = document.getElementById('createDocForm'); const editDocForm = document.getElementById('editDocForm'); const currentUserName = document.getElementById('currentUserName'); const editProfileBtn = document.getElementById('editProfileBtn'); const viewLogsBtn = document.getElementById('viewLogsBtn'); const createDocBtn = document.getElementById('createDocBtn'); const documentsList = document.getElementById('documentsList'); const logsList = document.getElementById('logsList'); const message = document.getElementById('message'); // 模态框相关元素 const editProfileModal = document.getElementById('editProfileModal'); const createDocModal = document.getElementById('createDocModal'); const editDocModal = document.getElementById('editDocModal'); const logsModal = document.getElementById('logsModal'); // 用户管理相关元素 const userManagementSection = document.getElementById('userManagementSection'); const usersList = document.getElementById('usersList'); const refreshUsersBtn = document.getElementById('refreshUsersBtn'); // API请求函数 async function apiRequest(url, options = {}) { const config = { headers: { 'Content-Type': 'application/json', ...options.headers }, ...options }; if (accessToken) { config.headers['Authorization'] = `Bearer ${accessToken}`; } try { const response = await fetch(`${API_BASE_URL}${url}`, config); if (response.status === 401) { // Token过期,清除本地存储并重新登录 accessToken = null; localStorage.removeItem('accessToken'); currentUser = null; showLoginSection(); showMessage('登录已过期,请重新登录', 'error'); return null; } if (!response.ok) { const errorData = await response.json().catch(() => ({})); throw new Error(errorData.detail || `HTTP error! status: ${response.status}`); } const result = await response.json(); return result; } catch (error) { console.error('API请求错误:', error); showMessage(`请求失败: ${error.message}`, 'error'); return null; } } // 显示消息提示 function showMessage(text, type = 'info') { message.textContent = text; message.className = `message ${type}`; message.style.display = 'block'; setTimeout(() => { message.style.display = 'none'; }, 3000); } // 用户认证相关函数 async function login(username, password) { const data = await apiRequest('/auth/login', { method: 'POST', body: JSON.stringify({ username, password }) }); if (data && data.access_token) { accessToken = data.access_token; localStorage.setItem('accessToken', accessToken); await loadCurrentUser(); showMainSection(); showMessage('登录成功', 'success'); return true; } return false; } async function register(userData) { // 将isAdmin添加到userData中 const registrationData = { ...userData, is_admin: document.getElementById('registerIsAdmin') ? document.getElementById('registerIsAdmin').checked : false }; const data = await apiRequest('/auth/register', { method: 'POST', body: JSON.stringify(registrationData) }); if (data) { showMessage('注册成功,请登录', 'success'); // 重置勾选框 if(document.getElementById('registerIsAdmin')) { document.getElementById('registerIsAdmin').checked = false; } showLoginSection(); return true; } return false; } async function logout() { await apiRequest('/auth/logout', { method: 'POST' }); accessToken = null; localStorage.removeItem('accessToken'); currentUser = null; showLoginSection(); showMessage('已退出登录', 'info'); } async function loadCurrentUser() { const data = await apiRequest('/users/me'); if (data) { currentUser = data; userInfo.textContent = `欢迎, ${data.username}`; currentUserName.textContent = data.username; return true; } return false; } async function updateUserProfile(updateData) { const data = await apiRequest('/users/me', { method: 'PUT', body: JSON.stringify(updateData) }); if (data) { await loadCurrentUser(); showMessage('个人信息更新成功', 'success'); return true; } return false; } // 文档管理相关函数 async function loadDocuments() { const data = await apiRequest('/documents'); if (data) { displayDocuments(data); return true; } return false; } async function createDocument(docData) { const data = await apiRequest('/documents', { method: 'POST', body: JSON.stringify(docData) }); if (data) { await loadDocuments(); showMessage('文档创建成功', 'success'); return true; } return false; } async function updateDocument(docId, docData) { const data = await apiRequest(`/documents/${docId}`, { method: 'PUT', body: JSON.stringify(docData) }); if (data) { await loadDocuments(); showMessage('文档更新成功', 'success'); return true; } return false; } async function deleteDocument(docId) { const data = await apiRequest(`/documents/${docId}`, { method: 'DELETE' }); if (data) { await loadDocuments(); showMessage('文档删除成功', 'success'); return true; } return false; } // 操作日志相关函数 async function loadLogs() { const data = await apiRequest('/logs/my'); if (data) { displayLogs(data); return true; } return false; } // 用户管理相关函数 async function loadUsers() { const data = await apiRequest('/users'); if (data) { displayUsers(data); return true; } return false; } async function deleteUser(userId) { if (confirm('确定要删除这个用户吗?此操作不可恢复。')) { const data = await apiRequest(`/users/${userId}`, { method: 'DELETE' }); if (data) { await loadUsers(); showMessage('用户删除成功', 'success'); return true; } } return false; } // 界面显示控制函数 function showLoginSection() { loginSection.style.display = 'block'; registerSection.style.display = 'none'; mainSection.style.display = 'none'; loginBtn.style.display = 'inline-block'; registerBtn.style.display = 'inline-block'; logoutBtn.style.display = 'none'; userInfo.style.display = 'none'; } function showRegisterSection() { loginSection.style.display = 'none'; registerSection.style.display = 'block'; mainSection.style.display = 'none'; } function showMainSection() { loginSection.style.display = 'none'; registerSection.style.display = 'none'; mainSection.style.display = 'block'; loginBtn.style.display = 'none'; registerBtn.style.display = 'none'; logoutBtn.style.display = 'inline-block'; userInfo.style.display = 'inline-block'; // 检查是否为管理员,如果是则显示用户管理界面 if (currentUser && currentUser.is_admin) { userManagementSection.style.display = 'block'; loadUsers(); } else { userManagementSection.style.display = 'none'; } loadDocuments(); } // 显示/隐藏模态框函数 function showModal(modal) { modal.style.display = 'flex'; } function hideModal(modal) { modal.style.display = 'none'; } // 文档显示函数 function displayDocuments(documents) { if (documents.length === 0) { documentsList.innerHTML = `

暂无文档

点击"创建新文档"按钮开始创建您的第一个文档

`; return; } documentsList.innerHTML = documents.map(doc => `
${escapeHtml(doc.title)}
类型: ${doc.file_type} 大小: ${formatFileSize(doc.file_size)} ${doc.is_public ? '公开' : '私有'}
${doc.description ? `
${escapeHtml(doc.description)}
` : ''}
${escapeHtml(doc.content.substring(0, 100))}${doc.content.length > 100 ? '...' : ''}
创建时间: ${formatDate(doc.created_at)}
`).join(''); } // 用户显示函数 function displayUsers(users) { if (users.length === 0) { usersList.innerHTML = '

暂无用户

'; return; } usersList.innerHTML = users.map(user => `
`).join(''); } // 日志显示函数 function displayLogs(logs) { if (logs.length === 0) { logsList.innerHTML = '

暂无操作日志

'; return; } logsList.innerHTML = logs.map(log => `
${escapeHtml(log.operation)} ${formatDate(log.created_at)}
详情: ${escapeHtml(log.details || '无')}
`).join(''); } // 工具函数 function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } function formatDate(dateString) { return new Date(dateString).toLocaleString('zh-CN'); } function formatFileSize(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } // 模态框操作函数 function openEditProfileModal() { if (!currentUser) return; document.getElementById('editEmail').value = currentUser.email || ''; document.getElementById('editFullName').value = currentUser.full_name || ''; document.getElementById('editPassword').value = ''; showModal(editProfileModal); } function openCreateDocumentModal() { document.getElementById('docTitle').value = ''; document.getElementById('docDescription').value = ''; document.getElementById('docContent').value = ''; document.getElementById('docType').value = 'txt'; document.getElementById('docPublic').checked = false; showModal(createDocModal); } async function openEditDocumentModal(docId) { const data = await apiRequest(`/documents/${docId}`); if (!data) return; document.getElementById('editDocId').value = docId; document.getElementById('editDocTitle').value = data.title; document.getElementById('editDocDescription').value = data.description || ''; document.getElementById('editDocContent').value = data.content; document.getElementById('editDocType').value = data.file_type; document.getElementById('editDocPublic').checked = data.is_public; showModal(editDocModal); } async function openLogsModal() { await loadLogs(); showModal(logsModal); } // 导航按钮事件 loginBtn.addEventListener('click', showLoginSection); registerBtn.addEventListener('click', showRegisterSection); logoutBtn.addEventListener('click', logout); // 表单切换链接 document.getElementById('showRegister').addEventListener('click', (e) => { e.preventDefault(); showRegisterSection(); }); document.getElementById('showLogin').addEventListener('click', (e) => { e.preventDefault(); showLoginSection(); }); // 删除文档按钮 document.getElementById('deleteDocBtn').addEventListener('click', async (e) => { e.preventDefault(); const docId = document.getElementById('editDocId').value; if (confirm('确定要删除这个文档吗?此操作不可恢复。')) { const success = await deleteDocument(docId); if (success) { hideModal(editDocModal); } } }); // 主界面按钮事件 editProfileBtn.addEventListener('click', openEditProfileModal); viewLogsBtn.addEventListener('click', openLogsModal); createDocBtn.addEventListener('click', openCreateDocumentModal); // 用户管理按钮事件 refreshUsersBtn.addEventListener('click', loadUsers); // 模态框关闭事件 document.getElementById('closeEditModal').addEventListener('click', () => hideModal(editProfileModal)); document.getElementById('closeCreateDocModal').addEventListener('click', () => hideModal(createDocModal)); document.getElementById('closeEditDocModal').addEventListener('click', () => hideModal(editDocModal)); document.getElementById('closeLogsModal').addEventListener('click', () => hideModal(logsModal)); // 点击模态框外部关闭 [editProfileModal, createDocModal, editDocModal, logsModal].forEach(modal => { modal.addEventListener('click', (e) => { if (e.target === modal) { hideModal(modal); } }); }); // 键盘事件:ESC键关闭模态框 document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { [editProfileModal, createDocModal, editDocModal, logsModal].forEach(modal => { if (modal.style.display === 'flex') { hideModal(modal); } }); } }); // 表单提交事件 loginForm.addEventListener('submit', async (e) => { e.preventDefault(); const username = document.getElementById('loginUsername').value; const password = document.getElementById('loginPassword').value; await login(username, password); }); registerForm.addEventListener('submit', async (e) => { e.preventDefault(); const userData = { username: document.getElementById('registerUsername').value, email: document.getElementById('registerEmail').value, full_name: document.getElementById('registerFullName').value, password: document.getElementById('registerPassword').value, is_admin: document.getElementById('registerIsAdmin').checked }; await register(userData); }); editProfileForm.addEventListener('submit', async (e) => { e.preventDefault(); const updateData = { email: document.getElementById('editEmail').value, full_name: document.getElementById('editFullName').value }; const newPassword = document.getElementById('editPassword').value; if (newPassword) { updateData.password = newPassword; } const success = await updateUserProfile(updateData); if (success) { hideModal(editProfileModal); } }); createDocForm.addEventListener('submit', async (e) => { e.preventDefault(); const docData = { title: document.getElementById('docTitle').value, description: document.getElementById('docDescription').value, content: document.getElementById('docContent').value, file_type: document.getElementById('docType').value, is_public: document.getElementById('docPublic').checked }; const success = await createDocument(docData); if (success) { hideModal(createDocModal); } }); editDocForm.addEventListener('submit', async (e) => { e.preventDefault(); const docId = document.getElementById('editDocId').value; const docData = { title: document.getElementById('editDocTitle').value, description: document.getElementById('editDocDescription').value, content: document.getElementById('editDocContent').value, file_type: document.getElementById('editDocType').value, is_public: document.getElementById('editDocPublic').checked }; const success = await updateDocument(docId, docData); if (success) { hideModal(editDocModal); } }); // 事件监听器 let isInitialized = false; // 防止重复初始化 document.addEventListener('DOMContentLoaded', async function() { // 防止重复初始化 if (isInitialized) { console.log('页面已初始化,跳过重复初始化'); return; } isInitialized = true; // 检查是否已登录 if (accessToken) { try { const success = await loadCurrentUser(); if (success) { showMainSection(); } else { // 如果loadCurrentUser返回false,说明token无效,清除token并显示登录界面 accessToken = null; localStorage.removeItem('accessToken'); showLoginSection(); } } catch (error) { // 捕获可能的错误,清除token并显示登录界面 console.error('初始化错误:', error); accessToken = null; localStorage.removeItem('accessToken'); showLoginSection(); } } else { showLoginSection(); } });