首次提交:初始化项目代码

This commit is contained in:
sunct
2026-07-31 14:44:48 +08:00
commit a4fe393571
119 changed files with 29105 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
// admin-menus.js - 菜单管理页面功能
function openAddMenuModal() {
document.getElementById('menuId').value = '';
document.getElementById('menuName').value = '';
document.getElementById('menuIcon').value = '';
document.getElementById('menuPath').value = '';
document.getElementById('menuSortOrder').value = '0';
document.getElementById('menuParentID').value = '';
document.getElementById('menuIsEnabled').checked = true;
document.getElementById('menuIsFixed').checked = false;
document.getElementById('menuModalTitle').textContent = '添加菜单';
document.getElementById('menuModal').style.display = 'flex';
}
function closeMenuModal() {
document.getElementById('menuModal').style.display = 'none';
}
function editMenu(id) {
fetch(`/api/admin/menus/${id}`)
.then(response => response.json())
.then(menu => {
document.getElementById('menuId').value = menu.id;
document.getElementById('menuName').value = menu.name;
document.getElementById('menuIcon').value = menu.icon || '';
document.getElementById('menuPath').value = menu.path;
document.getElementById('menuSortOrder').value = menu.sort_order || '0';
document.getElementById('menuParentID').value = menu.parent_id || '';
document.getElementById('menuIsEnabled').checked = menu.is_enabled;
document.getElementById('menuIsFixed').checked = menu.is_fixed;
document.getElementById('menuModalTitle').textContent = '编辑菜单';
document.getElementById('menuModal').style.display = 'flex';
})
.catch(error => {
showCustomAlert('error', '获取失败', '获取菜单信息失败');
});
}
function saveMenu(event) {
event.preventDefault();
const menuId = document.getElementById('menuId').value;
const data = {
name: document.getElementById('menuName').value,
icon: document.getElementById('menuIcon').value,
path: document.getElementById('menuPath').value,
sort_order: parseInt(document.getElementById('menuSortOrder').value) || 0,
parent_id: document.getElementById('menuParentID').value || null,
is_enabled: document.getElementById('menuIsEnabled').checked,
is_fixed: document.getElementById('menuIsFixed').checked
};
const url = menuId ? `/api/admin/menus/${menuId}` : '/api/admin/menus';
const method = menuId ? 'PUT' : 'POST';
fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '保存成功', menuId ? '菜单更新成功' : '菜单添加成功');
closeMenuModal();
window.location.reload();
} else {
showCustomAlert('error', '保存失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '保存失败', '网络请求失败');
});
}
function deleteMenu(id) {
if (!confirm('确定要删除该菜单吗?')) return;
fetch(`/api/admin/menus/${id}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '删除成功', '菜单删除成功');
window.location.reload();
} else {
showCustomAlert('error', '删除失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '删除失败', '网络请求失败');
});
}
+101
View File
@@ -0,0 +1,101 @@
// admin-portfolio.js - 作品集管理页面功能
function openAddPortfolioModal() {
document.getElementById('portfolioId').value = '';
document.getElementById('portfolioName').value = '';
document.getElementById('portfolioDescription').value = '';
document.getElementById('portfolioTechStack').value = '';
document.getElementById('portfolioURL').value = '';
document.getElementById('portfolioStartDate').value = '';
document.getElementById('portfolioEndDate').value = '';
document.getElementById('portfolioModalTitle').textContent = '添加项目';
document.getElementById('portfolioModal').style.display = 'flex';
}
function closePortfolioModal() {
document.getElementById('portfolioModal').style.display = 'none';
}
function editPortfolio(id) {
fetch(`/api/admin/portfolio/${id}`)
.then(response => response.json())
.then(item => {
document.getElementById('portfolioId').value = item.id;
document.getElementById('portfolioName').value = item.name;
document.getElementById('portfolioDescription').value = item.description;
document.getElementById('portfolioTechStack').value = item.tech_stack ? item.tech_stack.join(', ') : '';
document.getElementById('portfolioURL').value = item.url || '';
document.getElementById('portfolioStartDate').value = item.start_date || '';
document.getElementById('portfolioEndDate').value = item.end_date || '';
document.getElementById('portfolioModalTitle').textContent = '编辑项目';
document.getElementById('portfolioModal').style.display = 'flex';
})
.catch(error => {
showCustomAlert('error', '获取失败', '获取项目信息失败');
});
}
function savePortfolio(event) {
event.preventDefault();
const portfolioId = document.getElementById('portfolioId').value;
const userId = document.getElementById('portfolioUserId').value;
const techStack = document.getElementById('portfolioTechStack').value
.split(',')
.map(s => s.trim())
.filter(s => s);
const data = {
user_id: userId,
name: document.getElementById('portfolioName').value,
description: document.getElementById('portfolioDescription').value,
tech_stack: techStack,
url: document.getElementById('portfolioURL').value,
start_date: document.getElementById('portfolioStartDate').value,
end_date: document.getElementById('portfolioEndDate').value
};
const url = portfolioId ? `/api/admin/portfolio/${portfolioId}` : '/api/admin/portfolio';
const method = portfolioId ? 'PUT' : 'POST';
fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '保存成功', portfolioId ? '项目更新成功' : '项目添加成功');
closePortfolioModal();
window.location.reload();
} else {
showCustomAlert('error', '保存失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '保存失败', '网络请求失败');
});
}
function deletePortfolio(id) {
if (!confirm('确定要删除该项目吗?')) return;
fetch(`/api/admin/portfolio/${id}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '删除成功', '项目删除成功');
window.location.reload();
} else {
showCustomAlert('error', '删除失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '删除失败', '网络请求失败');
});
}
+38
View File
@@ -0,0 +1,38 @@
// admin-quiz.js - 面试题库页面功能
function generateQuestions() {
showCustomAlert('info', '生成中', '正在生成面试题目,请稍候...');
}
function filterFavorites() {
showCustomAlert('info', '筛选收藏', '已筛选收藏的题目');
}
function filterWrong() {
showCustomAlert('info', '筛选错题', '已筛选错题');
}
function clearAllRecords() {
if (!confirm('确定要清空所有答题记录吗?')) return;
showCustomAlert('success', '清空成功', '记录已清空');
}
function deleteFavorite(id) {
if (!confirm('确定要删除该收藏吗?')) return;
fetch(`/api/admin/favorites/${id}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '删除成功', '收藏已删除');
window.location.reload();
} else {
showCustomAlert('error', '删除失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '删除失败', '网络请求失败');
});
}
+33
View File
@@ -0,0 +1,33 @@
// admin-resume.js - 个人简历页面功能
function createResume(userId) {
fetch(`/api/admin/users/${userId}/resume`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
basic_info: {
name: '',
title: '',
email: '',
phone: '',
location: '',
website: '',
summary: ''
}
})
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '创建成功', '简历创建成功');
window.location.reload();
} else {
showCustomAlert('error', '创建失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '创建失败', '网络请求失败');
});
}
+61
View File
@@ -0,0 +1,61 @@
// admin-settings.js - 系统设置页面功能
function saveWebsiteConfig(event) {
event.preventDefault();
const data = {
website_domain: document.getElementById('websiteDomain').value,
website_title: document.getElementById('websiteTitle').value,
website_description: document.getElementById('websiteDesc').value,
website_keywords: document.getElementById('websiteKeywords').value,
website_logo: document.getElementById('websiteLogo').value
};
fetch('/api/admin/settings/website', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '保存成功', '网站配置已保存');
} else {
showCustomAlert('error', '保存失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '保存失败', '网络请求失败');
});
}
function saveAIConfig(event) {
event.preventDefault();
const data = {
ai_provider: document.getElementById('aiProvider').value,
ai_api_key: document.getElementById('aiAPIKey').value,
ai_api_secret: document.getElementById('aiAPISecret').value
};
fetch('/api/admin/settings/ai', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '保存成功', 'AI配置已保存');
} else {
showCustomAlert('error', '保存失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '保存失败', '网络请求失败');
});
}
+91
View File
@@ -0,0 +1,91 @@
// admin-users.js - 人员管理页面功能
function openAddUserModal() {
document.getElementById('userId').value = '';
document.getElementById('userName').value = '';
document.getElementById('userUsername').value = '';
document.getElementById('userEmail').value = '';
document.getElementById('userPhone').value = '';
document.getElementById('userRole').value = 'user';
document.getElementById('userModalTitle').textContent = '添加用户';
document.getElementById('userModal').style.display = 'flex';
}
function closeUserModal() {
document.getElementById('userModal').style.display = 'none';
}
function editUser(id) {
fetch(`/api/admin/users/${id}`)
.then(response => response.json())
.then(user => {
document.getElementById('userId').value = user.id;
document.getElementById('userName').value = user.name;
document.getElementById('userUsername').value = user.username;
document.getElementById('userEmail').value = user.email;
document.getElementById('userPhone').value = user.phone || '';
document.getElementById('userRole').value = user.role;
document.getElementById('userModalTitle').textContent = '编辑用户';
document.getElementById('userModal').style.display = 'flex';
})
.catch(error => {
showCustomAlert('error', '获取失败', '获取用户信息失败');
});
}
function saveUser(event) {
event.preventDefault();
const userId = document.getElementById('userId').value;
const data = {
name: document.getElementById('userName').value,
username: document.getElementById('userUsername').value,
email: document.getElementById('userEmail').value,
phone: document.getElementById('userPhone').value,
role: document.getElementById('userRole').value
};
const url = userId ? `/api/admin/users/${userId}` : '/api/admin/users';
const method = userId ? 'PUT' : 'POST';
fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '保存成功', userId ? '用户更新成功' : '用户添加成功');
closeUserModal();
window.location.reload();
} else {
showCustomAlert('error', '保存失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '保存失败', '网络请求失败');
});
}
function deleteUser(id) {
if (!confirm('确定要删除该用户吗?')) return;
fetch(`/api/admin/users/${id}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(result => {
if (result.success) {
showCustomAlert('success', '删除成功', '用户删除成功');
window.location.reload();
} else {
showCustomAlert('error', '删除失败', result.message || '操作失败');
}
})
.catch(error => {
showCustomAlert('error', '删除失败', '网络请求失败');
});
}
+97
View File
@@ -0,0 +1,97 @@
// admin.js - 后台管理公共功能模块
/**
* 侧边栏切换
*/
function toggleSidebar() {
const sidebar = document.getElementById('sidebar');
const mainArea = document.querySelector('.main-area');
const toggleIcon = document.querySelector('.sidebar-toggle i');
if (sidebar && mainArea && toggleIcon) {
if (sidebar.classList.contains('collapsed')) {
sidebar.classList.remove('collapsed');
mainArea.style.marginLeft = '256px';
toggleIcon.className = 'fas fa-chevron-left';
} else {
sidebar.classList.add('collapsed');
mainArea.style.marginLeft = '0';
toggleIcon.className = 'fas fa-chevron-right';
}
}
}
/**
* 自定义弹窗提示
* @param {string} type - 类型: success, error, info, warning
* @param {string} title - 标题
* @param {string} message - 消息内容
*/
function showCustomAlert(type, title, message) {
const modal = document.getElementById('customAlertModal');
const icon = document.getElementById('alertIcon');
const alertTitle = document.getElementById('alertTitle');
const alertMessage = document.getElementById('alertMessage');
if (!modal || !icon || !alertTitle || !alertMessage) return;
const icons = {
success: '<i class="fas fa-check-circle" style="color: #10b981;"></i>',
error: '<i class="fas fa-exclamation-circle" style="color: #ef4444;"></i>',
info: '<i class="fas fa-info-circle" style="color: #3b82f6;"></i>',
warning: '<i class="fas fa-exclamation-triangle" style="color: #f59e0b;"></i>'
};
icon.innerHTML = icons[type] || icons.info;
alertTitle.textContent = title;
alertMessage.textContent = message;
modal.style.display = 'flex';
}
/**
* 关闭自定义弹窗
*/
function closeCustomAlert() {
const modal = document.getElementById('customAlertModal');
if (modal) modal.style.display = 'none';
}
/**
* HTML转义,防止XSS攻击
* @param {string} text - 需要转义的文本
* @returns {string} 转义后的文本
*/
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
/**
* 验证邮箱格式
* @param {string} email - 邮箱地址
* @returns {boolean} 是否有效
*/
function isValidEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
/**
* 验证手机号格式
* @param {string} phone - 手机号码
* @returns {boolean} 是否有效
*/
function isValidPhone(phone) {
const re = /^1[3-9]\d{9}$/;
return re.test(phone);
}
// 点击模态框外部关闭弹窗
document.addEventListener('click', function(e) {
const alertModal = document.getElementById('customAlertModal');
if (alertModal && e.target === alertModal) {
closeCustomAlert();
}
});
+24
View File
@@ -0,0 +1,24 @@
function revealEmail(element) {
const maskedEmail = element.getAttribute('data-email');
if (!maskedEmail) return;
if (element.classList.contains('revealed')) {
window.location.href = 'mailto:' + maskedEmail;
return;
}
element.classList.add('revealed');
const emailParts = maskedEmail.split('@');
if (emailParts.length === 2) {
element.innerHTML = '<i class="fas fa-envelope"></i> <a href="mailto:' + maskedEmail + '" style="color: inherit; text-decoration: none;">' + maskedEmail + '</a>';
}
}
document.addEventListener('DOMContentLoaded', function() {
const emailElements = document.querySelectorAll('.email-protected');
emailElements.forEach(function(el) {
el.style.cursor = 'pointer';
el.title = '点击查看完整邮箱';
});
});