|
|
<!DOCTYPE html>
|
|
|
<html lang="zh-CN">
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>导入学生名单 - 智慧点名系统</title>
|
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
|
<style>
|
|
|
.import-container {
|
|
|
max-width: 600px;
|
|
|
margin: 0 auto;
|
|
|
background: white;
|
|
|
padding: 30px;
|
|
|
border-radius: 10px;
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
}
|
|
|
|
|
|
.import-header {
|
|
|
text-align: center;
|
|
|
margin-bottom: 30px;
|
|
|
}
|
|
|
|
|
|
.import-form {
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
.file-input {
|
|
|
width: 100%;
|
|
|
padding: 10px;
|
|
|
margin-bottom: 15px;
|
|
|
border: 2px dashed #ddd;
|
|
|
border-radius: 5px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.import-btn {
|
|
|
width: 100%;
|
|
|
padding: 12px;
|
|
|
background-color: #27ae60;
|
|
|
color: white;
|
|
|
border: none;
|
|
|
border-radius: 5px;
|
|
|
cursor: pointer;
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
|
|
|
.import-btn:disabled {
|
|
|
background-color: #95a5a6;
|
|
|
cursor: not-allowed;
|
|
|
}
|
|
|
|
|
|
.result-message {
|
|
|
padding: 15px;
|
|
|
border-radius: 5px;
|
|
|
margin-top: 20px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.success {
|
|
|
background-color: #d4edda;
|
|
|
color: #155724;
|
|
|
border: 1px solid #c3e6cb;
|
|
|
}
|
|
|
|
|
|
.error {
|
|
|
background-color: #f8d7da;
|
|
|
color: #721c24;
|
|
|
border: 1px solid #f5c6cb;
|
|
|
}
|
|
|
|
|
|
.template-download {
|
|
|
margin-top: 30px;
|
|
|
padding: 20px;
|
|
|
background-color: #f8f9fa;
|
|
|
border-radius: 5px;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.requirements {
|
|
|
background-color: #fff3cd;
|
|
|
border: 1px solid #ffeaa7;
|
|
|
border-radius: 5px;
|
|
|
padding: 15px;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
<div class="container">
|
|
|
<header>
|
|
|
<h1>智慧点名系统</h1>
|
|
|
<a href="/" class="back-link">← 返回首页</a>
|
|
|
</header>
|
|
|
|
|
|
<div class="import-container">
|
|
|
<div class="import-header">
|
|
|
<h2>导入学生名单</h2>
|
|
|
<p>通过Excel文件批量导入学生信息</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="requirements">
|
|
|
<h3>📋 导入要求</h3>
|
|
|
<p>• Excel文件必须包含 <strong>学号</strong> 和 <strong>姓名</strong> 两列</p>
|
|
|
<p>• 所有学生将自动分配到 <strong>软工K班</strong></p>
|
|
|
<p>• 专业默认为 <strong>软件工程</strong></p>
|
|
|
<p>• 初始积分和点名次数为 0</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="template-download">
|
|
|
<h3>📥 下载模板文件</h3>
|
|
|
<p>确保Excel文件包含以下列:<strong>学号、姓名</strong></p>
|
|
|
<button onclick="downloadTemplate()" class="btn btn-primary">下载模板</button>
|
|
|
</div>
|
|
|
|
|
|
<form id="importForm" class="import-form" enctype="multipart/form-data">
|
|
|
<input type="file" name="excel_file" accept=".xlsx,.xls" class="file-input" required>
|
|
|
<button type="submit" class="import-btn" id="submitBtn">上传并导入</button>
|
|
|
</form>
|
|
|
|
|
|
<div id="result" class="result-message" style="display: none;"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<script>
|
|
|
document.getElementById('importForm').addEventListener('submit', async (e) => {
|
|
|
e.preventDefault();
|
|
|
const submitBtn = document.getElementById('submitBtn');
|
|
|
const resultDiv = document.getElementById('result');
|
|
|
const formData = new FormData(e.target);
|
|
|
|
|
|
// 禁用按钮,显示加载状态
|
|
|
submitBtn.disabled = true;
|
|
|
submitBtn.textContent = '导入中...';
|
|
|
resultDiv.style.display = 'none';
|
|
|
|
|
|
try {
|
|
|
const res = await fetch('/api/students/import', {
|
|
|
method: 'POST',
|
|
|
body: formData
|
|
|
});
|
|
|
const data = await res.json();
|
|
|
|
|
|
// 显示结果
|
|
|
resultDiv.style.display = 'block';
|
|
|
resultDiv.className = data.success ? 'result-message success' : 'result-message error';
|
|
|
resultDiv.textContent = data.message;
|
|
|
|
|
|
if (data.success) {
|
|
|
// 导入成功,3秒后跳转首页
|
|
|
setTimeout(() => {
|
|
|
window.location.href = '/';
|
|
|
}, 3000);
|
|
|
}
|
|
|
|
|
|
} catch (err) {
|
|
|
resultDiv.style.display = 'block';
|
|
|
resultDiv.className = 'result-message error';
|
|
|
resultDiv.textContent = '导入失败:网络错误,请重试';
|
|
|
console.error('导入错误:', err);
|
|
|
} finally {
|
|
|
// 恢复按钮状态
|
|
|
submitBtn.disabled = false;
|
|
|
submitBtn.textContent = '上传并导入';
|
|
|
}
|
|
|
});
|
|
|
|
|
|
function downloadTemplate() {
|
|
|
// 创建模板数据(只需要学号和姓名)
|
|
|
const templateData = [
|
|
|
['学号', '姓名'],
|
|
|
['2021001', '张三'],
|
|
|
['2021002', '李四'],
|
|
|
['2021003', '王五'],
|
|
|
['2021004', '赵六'],
|
|
|
['2021005', '钱七']
|
|
|
];
|
|
|
|
|
|
// 创建CSV内容
|
|
|
const csvContent = "data:text/csv;charset=utf-8,\uFEFF" + templateData.map(row => row.join(',')).join('\n');
|
|
|
const encodedUri = encodeURI(csvContent);
|
|
|
const link = document.createElement('a');
|
|
|
|
|
|
link.setAttribute('href', encodedUri);
|
|
|
link.setAttribute('download', '学生名单模板.csv');
|
|
|
document.body.appendChild(link);
|
|
|
link.click();
|
|
|
document.body.removeChild(link);
|
|
|
}
|
|
|
|
|
|
// 拖拽上传功能
|
|
|
const fileInput = document.querySelector('.file-input');
|
|
|
fileInput.addEventListener('dragover', (e) => {
|
|
|
e.preventDefault();
|
|
|
fileInput.style.borderColor = '#3498db';
|
|
|
fileInput.style.backgroundColor = '#f8f9fa';
|
|
|
});
|
|
|
|
|
|
fileInput.addEventListener('dragleave', (e) => {
|
|
|
e.preventDefault();
|
|
|
fileInput.style.borderColor = '#ddd';
|
|
|
fileInput.style.backgroundColor = '';
|
|
|
});
|
|
|
|
|
|
fileInput.addEventListener('drop', (e) => {
|
|
|
e.preventDefault();
|
|
|
fileInput.style.borderColor = '#ddd';
|
|
|
fileInput.style.backgroundColor = '';
|
|
|
if (e.dataTransfer.files.length) {
|
|
|
fileInput.files = e.dataTransfer.files;
|
|
|
}
|
|
|
});
|
|
|
</script>
|
|
|
</body>
|
|
|
</html> |