This commit is contained in:
Harry
2026-04-25 10:09:16 +08:00
committed by GitHub
commit bf215c4b9f
15 changed files with 2482 additions and 0 deletions

264
admin.js Normal file
View File

@@ -0,0 +1,264 @@
// 后台管理JavaScript - 支持服务器和本地双模式
// 状态管理
let isLoggedIn = sessionStorage.getItem('isAdminLoggedIn') === 'true';
let authToken = sessionStorage.getItem('authToken') || '';
// DOM元素
const loginSection = document.getElementById('loginSection');
const adminPanel = document.getElementById('adminPanel');
const loginForm = document.getElementById('loginForm');
const logoutBtn = document.getElementById('logoutBtn');
const createListForm = document.getElementById('createListForm');
const rollCallListsDiv = document.getElementById('rollCallLists');
const rollCallRecordsDiv = document.getElementById('rollCallRecords');
const qrModal = document.getElementById('qrModal');
const qrCodeDiv = document.getElementById('qrCode');
const rollCallCodeSpan = document.getElementById('rollCallCode');
// QRCode实例
const qrCode = new SimpleQRCode();
// 初始化
document.addEventListener('DOMContentLoaded', () => {
// 显示运行模式
const modeText = dataStorage.isServerMode ? '服务器模式' : '本地模式';
const modeIndicator = document.getElementById('modeIndicator');
if (modeIndicator) {
modeIndicator.textContent = `当前运行模式: ${modeText}`;
if (!dataStorage.isServerMode) {
modeIndicator.textContent += ' (数据保存在浏览器本地)';
}
}
console.log(`点名系统运行在: ${modeText}`);
if (isLoggedIn) {
showAdminPanel();
loadLists();
loadRecords();
}
});
// 登录
loginForm.addEventListener('submit', async (e) => {
e.preventDefault();
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
try {
const result = await dataStorage.login(username, password);
isLoggedIn = true;
authToken = result.token;
sessionStorage.setItem('isAdminLoggedIn', 'true');
sessionStorage.setItem('authToken', authToken);
showAdminPanel();
await loadLists();
await loadRecords();
} catch (error) {
alert('登录失败:' + error.message);
}
});
// 退出登录
logoutBtn.addEventListener('click', () => {
isLoggedIn = false;
authToken = '';
sessionStorage.removeItem('isAdminLoggedIn');
sessionStorage.removeItem('authToken');
loginSection.style.display = 'block';
adminPanel.style.display = 'none';
});
// 显示管理面板
function showAdminPanel() {
loginSection.style.display = 'none';
adminPanel.style.display = 'block';
}
// 加载点名列表
async function loadLists() {
try {
const lists = await dataStorage.getLists();
renderLists(lists);
} catch (error) {
console.error('加载列表失败:', error);
rollCallListsDiv.innerHTML = '<p style="color: red;">加载失败:' + error.message + '</p>';
}
}
// 加载点名记录
async function loadRecords() {
try {
const records = await dataStorage.getRecords();
renderRecords(records);
} catch (error) {
console.error('加载记录失败:', error);
rollCallRecordsDiv.innerHTML = '<p style="color: red;">加载失败:' + error.message + '</p>';
}
}
// 创建点名名单
createListForm.addEventListener('submit', async (e) => {
e.preventDefault();
const listName = document.getElementById('listName').value;
const memberListText = document.getElementById('memberList').value;
const members = memberListText.split('\n').filter(name => name.trim() !== '').map(name => name.trim());
try {
const newList = await dataStorage.createList(listName, members);
// 清空表单
createListForm.reset();
// 重新加载列表
await loadLists();
// 显示二维码
showQRCode(newList);
} catch (error) {
alert('创建失败:' + error.message);
}
});
// 显示二维码
function showQRCode(list) {
qrModal.style.display = 'block';
rollCallCodeSpan.textContent = list.code;
// 生成二维码URL
let url;
if (dataStorage.isServerMode) {
// 服务器模式:使用当前域名
url = `${window.location.origin}${window.location.pathname.replace('admin.html', 'index.html')}?code=${list.code}`;
} else {
// 本地模式:使用相对路径
url = `index.html?code=${list.code}`;
}
qrCodeDiv.innerHTML = '';
// 创建canvas元素
const canvas = document.createElement('canvas');
qrCodeDiv.appendChild(canvas);
// 使用本地QRCode生成器
try {
qrCode.toCanvas(canvas, url, {
width: 200,
margin: 2
});
} catch (error) {
console.error('二维码生成错误:', error);
qrCodeDiv.innerHTML = '<p style="color: red;">二维码生成失败</p>';
}
}
// 关闭弹窗
document.querySelector('.close').addEventListener('click', () => {
qrModal.style.display = 'none';
});
window.addEventListener('click', (e) => {
if (e.target === qrModal) {
qrModal.style.display = 'none';
}
});
// 渲染点名列表
function renderLists(lists) {
if (!lists || lists.length === 0) {
rollCallListsDiv.innerHTML = '<p>暂无点名列表</p>';
return;
}
rollCallListsDiv.innerHTML = lists.map(list => `
<div class="list-item">
<div class="list-item-header">
<span class="list-item-title">${list.name}</span>
<span class="list-item-code">编号:${list.code}</span>
</div>
<p>创建时间:${list.createdAt}</p>
<p>成员数:${list.members.length} | 已点名:${list.members.filter(m => m.completed).length}</p>
<div class="list-item-actions">
<button class="btn btn-primary" onclick="showQRCodeById(${list.id})">查看二维码</button>
<button class="btn btn-secondary" onclick="editList(${list.id})">编辑</button>
<button class="btn btn-danger" onclick="deleteList(${list.id})">删除</button>
</div>
</div>
`).join('');
}
// 显示二维码通过ID
async function showQRCodeById(id) {
try {
const lists = await dataStorage.getLists();
const list = lists.find(l => l.id === id);
if (list) {
showQRCode(list);
}
} catch (error) {
alert('获取列表失败:' + error.message);
}
}
// 编辑名单
async function editList(id) {
try {
const lists = await dataStorage.getLists();
const list = lists.find(l => l.id === id);
if (!list) return;
const newName = prompt('请输入新的名单名称:', list.name);
if (newName === null) return;
const newMembersText = prompt('请输入新的名单成员(每行一个姓名):', list.members.map(m => m.name).join('\n'));
if (newMembersText === null) return;
const newMembers = newMembersText.split('\n').filter(name => name.trim() !== '').map(name => name.trim());
await dataStorage.updateList(id, newName, newMembers);
await loadLists();
} catch (error) {
alert('编辑失败:' + error.message);
}
}
// 删除名单
async function deleteList(id) {
if (confirm('确定要删除这个点名名单吗?')) {
try {
await dataStorage.deleteList(id);
await loadLists();
} catch (error) {
alert('删除失败:' + error.message);
}
}
}
// 渲染点名记录
function renderRecords(records) {
if (!records || records.length === 0) {
rollCallRecordsDiv.innerHTML = '<p>暂无点名记录</p>';
return;
}
rollCallRecordsDiv.innerHTML = records.map(record => `
<div class="record-item">
<div class="record-header">
<span class="record-name">${record.name}</span>
<span class="record-time">${record.timestamp}</span>
</div>
<p>名单:${record.listName}</p>
<p>编号:${record.code}</p>
</div>
`).join('');
}
// 暴露函数到全局
window.showQRCodeById = showQRCodeById;
window.editList = editList;
window.deleteList = deleteList;