First
This commit is contained in:
264
admin.js
Normal file
264
admin.js
Normal 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;
|
||||
Reference in New Issue
Block a user