首次提交:初始化项目代码
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 380 KiB |
@@ -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', '删除失败', '网络请求失败');
|
||||
});
|
||||
}
|
||||
@@ -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', '删除失败', '网络请求失败');
|
||||
});
|
||||
}
|
||||
@@ -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', '删除失败', '网络请求失败');
|
||||
});
|
||||
}
|
||||
@@ -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', '创建失败', '网络请求失败');
|
||||
});
|
||||
}
|
||||
@@ -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', '保存失败', '网络请求失败');
|
||||
});
|
||||
}
|
||||
@@ -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', '删除失败', '网络请求失败');
|
||||
});
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
@@ -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 = '点击查看完整邮箱';
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user