a3eb5c7b2d
从百度网盘 /apps/bypy/dofile/ 下载的完整项目结构,包含: - dofile/: Flask 后端(端口 5000)+ 静态前端(端口 6002) - officefile/: 项目相关文档 - .gitignore: Python venv / 日志 / 缓存 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
391 lines
14 KiB
JavaScript
391 lines
14 KiB
JavaScript
// Admin Panel JavaScript
|
|
|
|
let currentArticles = [];
|
|
let currentResources = [];
|
|
let currentTeamMembers = [];
|
|
|
|
// 检查管理员权限
|
|
async function checkAdminAccess() {
|
|
try {
|
|
const response = await window.DAELAPI.auth.checkAuth();
|
|
if (!response.authenticated || !response.user.is_admin) {
|
|
alert('需要管理员权限才能访问此页面');
|
|
window.location.href = 'website.html';
|
|
return false;
|
|
}
|
|
document.getElementById('admin-user').textContent = `管理员: ${response.user.username}`;
|
|
return true;
|
|
} catch (error) {
|
|
alert('无法验证权限,请先登录');
|
|
window.location.href = 'login.html';
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Tab切换
|
|
document.querySelectorAll('.admin-tab').forEach(tab => {
|
|
tab.addEventListener('click', () => {
|
|
const tabName = tab.dataset.tab;
|
|
|
|
// 更新tab样式
|
|
document.querySelectorAll('.admin-tab').forEach(t => {
|
|
t.classList.remove('active', 'border-black', 'text-black');
|
|
t.classList.add('text-gray-500');
|
|
});
|
|
tab.classList.add('active', 'border-black', 'text-black');
|
|
tab.classList.remove('text-gray-500');
|
|
|
|
// 更新内容
|
|
document.querySelectorAll('.admin-tab-content').forEach(content => {
|
|
content.classList.add('hidden');
|
|
});
|
|
document.getElementById(`tab-${tabName}`).classList.remove('hidden');
|
|
|
|
// 加载对应内容
|
|
if (tabName === 'articles') loadArticles();
|
|
else if (tabName === 'resources') loadResources();
|
|
else if (tabName === 'team') loadTeamMembers();
|
|
});
|
|
});
|
|
|
|
// 加载文章列表
|
|
async function loadArticles() {
|
|
try {
|
|
const response = await window.DAELAPI.content.getArticles('news', false);
|
|
currentArticles = response.articles;
|
|
displayArticles(currentArticles);
|
|
} catch (error) {
|
|
console.error('Failed to load articles:', error);
|
|
document.getElementById('articles-list').innerHTML = '<p class="text-red-600">加载失败</p>';
|
|
}
|
|
}
|
|
|
|
// 显示文章列表
|
|
function displayArticles(articles) {
|
|
const container = document.getElementById('articles-list');
|
|
if (articles.length === 0) {
|
|
container.innerHTML = '<p class="text-gray-500">暂无文章</p>';
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = articles.map(article => `
|
|
<div class="bg-white border border-gray-200 p-6 rounded">
|
|
<div class="flex justify-between items-start">
|
|
<div class="flex-1">
|
|
<h3 class="text-lg font-bold mb-2">${article.title}</h3>
|
|
<p class="text-sm text-gray-500 mb-2">${article.summary || article.content.substring(0, 100)}...</p>
|
|
<div class="flex gap-4 text-xs text-gray-400">
|
|
<span>分类: ${article.category}</span>
|
|
<span>${article.is_protected ? '🔒 受保护' : '公开'}</span>
|
|
<span>${article.published ? '已发布' : '草稿'}</span>
|
|
<span>${new Date(article.created_at).toLocaleDateString()}</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-2 ml-4">
|
|
<button onclick="editArticle(${article.id})" class="text-sm text-blue-600 hover:text-blue-800">编辑</button>
|
|
<button onclick="deleteArticle(${article.id})" class="text-sm text-red-600 hover:text-red-800">删除</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// 显示文章表单
|
|
function showArticleForm(articleId = null) {
|
|
const modal = document.getElementById('article-modal');
|
|
const form = document.getElementById('article-form');
|
|
const title = document.getElementById('article-modal-title');
|
|
|
|
if (articleId) {
|
|
const article = currentArticles.find(a => a.id === articleId);
|
|
if (article) {
|
|
title.textContent = '编辑文章';
|
|
document.getElementById('article-id').value = article.id;
|
|
document.getElementById('article-title').value = article.title;
|
|
document.getElementById('article-summary').value = article.summary || '';
|
|
document.getElementById('article-content').value = article.content;
|
|
document.getElementById('article-category').value = article.category;
|
|
document.getElementById('article-published').value = article.published.toString();
|
|
document.getElementById('article-protected').checked = article.is_protected;
|
|
}
|
|
} else {
|
|
title.textContent = '新建文章';
|
|
form.reset();
|
|
document.getElementById('article-id').value = '';
|
|
}
|
|
|
|
modal.classList.remove('hidden');
|
|
}
|
|
|
|
// 关闭文章表单
|
|
function closeArticleForm() {
|
|
document.getElementById('article-modal').classList.add('hidden');
|
|
}
|
|
|
|
// 保存文章
|
|
async function saveArticle(event) {
|
|
event.preventDefault();
|
|
|
|
const articleId = document.getElementById('article-id').value;
|
|
const articleData = {
|
|
title: document.getElementById('article-title').value,
|
|
summary: document.getElementById('article-summary').value,
|
|
content: document.getElementById('article-content').value,
|
|
category: document.getElementById('article-category').value,
|
|
published: document.getElementById('article-published').value === 'true',
|
|
is_protected: document.getElementById('article-protected').checked
|
|
};
|
|
|
|
try {
|
|
if (articleId) {
|
|
await window.DAELAPI.content.updateArticle(articleId, articleData);
|
|
} else {
|
|
await window.DAELAPI.content.createArticle(articleData);
|
|
}
|
|
closeArticleForm();
|
|
loadArticles();
|
|
} catch (error) {
|
|
alert('保存失败: ' + error.message);
|
|
}
|
|
}
|
|
|
|
// 编辑文章
|
|
function editArticle(articleId) {
|
|
showArticleForm(articleId);
|
|
}
|
|
|
|
// 删除文章
|
|
async function deleteArticle(articleId) {
|
|
if (!confirm('确定要删除这篇文章吗?')) return;
|
|
|
|
try {
|
|
await window.DAELAPI.content.deleteArticle(articleId);
|
|
loadArticles();
|
|
} catch (error) {
|
|
alert('删除失败: ' + error.message);
|
|
}
|
|
}
|
|
|
|
// 加载资源列表
|
|
async function loadResources() {
|
|
try {
|
|
const response = await window.DAELAPI.content.getResources();
|
|
currentResources = response.resources;
|
|
displayResources(currentResources);
|
|
} catch (error) {
|
|
console.error('Failed to load resources:', error);
|
|
document.getElementById('resources-list').innerHTML = '<p class="text-red-600">加载失败</p>';
|
|
}
|
|
}
|
|
|
|
// 显示资源列表
|
|
function displayResources(resources) {
|
|
const container = document.getElementById('resources-list');
|
|
if (resources.length === 0) {
|
|
container.innerHTML = '<p class="text-gray-500">暂无资源</p>';
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = resources.map(resource => `
|
|
<div class="bg-white border border-gray-200 p-6 rounded">
|
|
<div class="flex justify-between items-start">
|
|
<div class="flex-1">
|
|
<h3 class="text-lg font-bold mb-2">${resource.name}</h3>
|
|
<p class="text-sm text-gray-500 mb-2">${resource.description || ''}</p>
|
|
<div class="flex gap-4 text-xs text-gray-400">
|
|
<span>分类: ${resource.category}</span>
|
|
<span>${resource.is_protected ? '🔒 受保护' : '公开'}</span>
|
|
<span>大小: ${(resource.file_size / 1024 / 1024).toFixed(2)} MB</span>
|
|
<span>下载: ${resource.download_count} 次</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-2 ml-4">
|
|
<button onclick="window.DAELAPI.api.downloadResource(${resource.id})" class="text-sm text-blue-600 hover:text-blue-800">下载</button>
|
|
<button onclick="deleteResource(${resource.id})" class="text-sm text-red-600 hover:text-red-800">删除</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// 显示资源表单
|
|
function showResourceForm() {
|
|
document.getElementById('resource-modal').classList.remove('hidden');
|
|
}
|
|
|
|
// 关闭资源表单
|
|
function closeResourceForm() {
|
|
document.getElementById('resource-modal').classList.add('hidden');
|
|
document.getElementById('resource-form').reset();
|
|
}
|
|
|
|
// 保存资源
|
|
async function saveResource(event) {
|
|
event.preventDefault();
|
|
|
|
const fileInput = document.getElementById('resource-file');
|
|
if (!fileInput.files[0]) {
|
|
alert('请选择文件');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await window.DAELAPI.content.uploadResource(
|
|
fileInput.files[0],
|
|
document.getElementById('resource-name').value,
|
|
document.getElementById('resource-description').value,
|
|
document.getElementById('resource-category').value,
|
|
document.getElementById('resource-protected').checked
|
|
);
|
|
closeResourceForm();
|
|
loadResources();
|
|
} catch (error) {
|
|
alert('上传失败: ' + error.message);
|
|
}
|
|
}
|
|
|
|
// 删除资源
|
|
async function deleteResource(resourceId) {
|
|
if (!confirm('确定要删除这个资源吗?')) return;
|
|
// 注意:需要添加删除资源的API端点
|
|
alert('删除功能需要后端支持');
|
|
}
|
|
|
|
// 加载团队成员
|
|
async function loadTeamMembers() {
|
|
try {
|
|
const response = await window.DAELAPI.content.getTeam();
|
|
currentTeamMembers = response.members;
|
|
displayTeamMembers(currentTeamMembers);
|
|
} catch (error) {
|
|
console.error('Failed to load team members:', error);
|
|
document.getElementById('team-list').innerHTML = '<p class="text-red-600">加载失败</p>';
|
|
}
|
|
}
|
|
|
|
// 显示团队成员
|
|
function displayTeamMembers(members) {
|
|
const container = document.getElementById('team-list');
|
|
if (members.length === 0) {
|
|
container.innerHTML = '<p class="text-gray-500">暂无成员</p>';
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = members.map(member => `
|
|
<div class="bg-white border border-gray-200 p-6 rounded">
|
|
<div class="flex justify-between items-start">
|
|
<div class="flex-1">
|
|
<h3 class="text-lg font-bold mb-2">${member.name}</h3>
|
|
<p class="text-sm text-gray-600 mb-2">${member.title || ''}</p>
|
|
<p class="text-sm text-gray-500 mb-2">${member.bio || ''}</p>
|
|
<div class="flex gap-4 text-xs text-gray-400">
|
|
<span>角色: ${member.role}</span>
|
|
<span>排序: ${member.order}</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex gap-2 ml-4">
|
|
<button onclick="editTeamMember(${member.id})" class="text-sm text-blue-600 hover:text-blue-800">编辑</button>
|
|
<button onclick="deleteTeamMember(${member.id})" class="text-sm text-red-600 hover:text-red-800">删除</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`).join('');
|
|
}
|
|
|
|
// 显示团队成员表单
|
|
function showTeamForm(memberId = null) {
|
|
const modal = document.getElementById('team-modal');
|
|
const form = document.getElementById('team-form');
|
|
|
|
if (memberId) {
|
|
const member = currentTeamMembers.find(m => m.id === memberId);
|
|
if (member) {
|
|
document.getElementById('team-id').value = member.id;
|
|
document.getElementById('team-name').value = member.name;
|
|
document.getElementById('team-title').value = member.title || '';
|
|
document.getElementById('team-title-en').value = member.title_en || '';
|
|
document.getElementById('team-bio').value = member.bio || '';
|
|
document.getElementById('team-bio-en').value = member.bio_en || '';
|
|
document.getElementById('team-role').value = member.role;
|
|
document.getElementById('team-order').value = member.order;
|
|
document.getElementById('team-email').value = member.email || '';
|
|
document.getElementById('team-website').value = member.website || '';
|
|
}
|
|
} else {
|
|
form.reset();
|
|
document.getElementById('team-id').value = '';
|
|
}
|
|
|
|
modal.classList.remove('hidden');
|
|
}
|
|
|
|
// 关闭团队成员表单
|
|
function closeTeamForm() {
|
|
document.getElementById('team-modal').classList.add('hidden');
|
|
}
|
|
|
|
// 保存团队成员
|
|
async function saveTeamMember(event) {
|
|
event.preventDefault();
|
|
|
|
const memberId = document.getElementById('team-id').value;
|
|
const memberData = {
|
|
name: document.getElementById('team-name').value,
|
|
title: document.getElementById('team-title').value,
|
|
title_en: document.getElementById('team-title-en').value,
|
|
bio: document.getElementById('team-bio').value,
|
|
bio_en: document.getElementById('team-bio-en').value,
|
|
role: document.getElementById('team-role').value,
|
|
order: parseInt(document.getElementById('team-order').value) || 0,
|
|
email: document.getElementById('team-email').value,
|
|
website: document.getElementById('team-website').value
|
|
};
|
|
|
|
try {
|
|
if (memberId) {
|
|
// 更新功能需要后端支持
|
|
alert('更新功能需要后端支持');
|
|
} else {
|
|
await window.DAELAPI.content.createTeamMember(memberData);
|
|
}
|
|
closeTeamForm();
|
|
loadTeamMembers();
|
|
} catch (error) {
|
|
alert('保存失败: ' + error.message);
|
|
}
|
|
}
|
|
|
|
// 编辑团队成员
|
|
function editTeamMember(memberId) {
|
|
showTeamForm(memberId);
|
|
}
|
|
|
|
// 删除团队成员
|
|
async function deleteTeamMember(memberId) {
|
|
if (!confirm('确定要删除这个成员吗?')) return;
|
|
// 注意:需要添加删除成员的API端点
|
|
alert('删除功能需要后端支持');
|
|
}
|
|
|
|
// 初始化
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
if (await checkAdminAccess()) {
|
|
loadArticles();
|
|
|
|
// 退出按钮
|
|
document.getElementById('logout-btn').addEventListener('click', async () => {
|
|
await logout();
|
|
});
|
|
}
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|