html 简易题库单网页
1. style.css
/* 基础样式 */
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
margin: 0;
padding: 0;
transition: all 0.3s ease;
}
.hidden {
display: none;
}
/* 共用组件样式 */
button {
cursor: pointer;
transition: all 0.2s;
border-radius: 4px;
padding: 10px 15px;
font-size: 16px;
border: none;
margin: 5px;
}
/* 设置面板 */
#setup-panel {
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f9f9f9;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
#quiz-select {
padding: 8px;
border-radius: 4px;
border: 1px solid #ddd;
margin-right: 10px;
min-width: 200px;
}
/* 答题面板 */
#quiz-panel {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
#quiz-name {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 10px;
}
.stats {
background-color: #f0f8ff;
padding: 10px;
border-radius: 5px;
margin: 15px 0;
display: flex;
justify-content: space-around;
}
#question-title {
color: #2c3e50;
margin-bottom: 20px;
}
/* 选项样式 */
.option {
margin: 10px 0;
padding: 12px;
border: 1px solid #ddd;
border-radius: 5px;
cursor: pointer;
transition: all 0.2s;
}
.option:hover {
background-color: #f0f8ff;
}
.option.active {
background-color: #e0e0e0;
}
/* 解析区域 */
.analysis {
margin-top: 20px;
padding: 15px;
background-color: #f9f9f9;
border-left: 4px solid #3498db;
border-radius: 0 5px 5px 0;
}
/* 解析区域 */
.analysis-error {
border-left: 4px solid #cf5959;
}
/* 下一题按钮 */
#next-btn {
background-color: #3498db;
color: white;
width: 100%;
margin-top: 20px;
}
#next-btn:hover {
background-color: #2980b9;
}
/* 重新开始按钮 */
#quiz-panel button[onclick="restartQuiz()"] {
background-color: #e74c3c;
color: white;
width: 100%;
}
#quiz-panel button[onclick="restartQuiz()"]:hover {
background-color: #c0392b;
}
/* 移动端样式 */
@media (max-width: 768px) {
body {
padding: 10px;
}
#setup-panel, #quiz-panel {
padding: 15px;
width: calc(100% - 30px);
}
#quiz-select {
display: block;
width: 100%;
margin: 10px 0;
}
button {
width: 100%;
margin: 10px 0;
}
.stats {
flex-direction: column;
gap: 8px;
}
.option {
padding: 15px;
}
}
/* PC端增强样式 */
@media (min-width: 769px) {
#setup-panel {
margin-top: 50px;
}
#quiz-panel {
margin-top: 30px;
}
button {
min-width: 120px;
}
#next-btn {
width: auto;
float: right;
}
#quiz-panel button[onclick="restartQuiz()"] {
width: auto;
display: block;
margin: 20px auto;
}
}
2. keyboard-control.js
// keyboard-control.js
document.addEventListener('DOMContentLoaded', () => {
// 全局键盘事件监听
document.addEventListener('keydown', (e) => {
// 检查是否按下Enter键(键码13)
if (e.key === 'Enter') {
const nextBtn = document.getElementById('next-btn');
// 检查下一题按钮是否存在且可见
if (nextBtn && !nextBtn.classList.contains('hidden')) {
// 模拟点击事件
nextBtn.click();
// 可选:添加视觉反馈
nextBtn.classList.add('active');
setTimeout(() => {
nextBtn.classList.remove('active');
}, 100);
}
}
});
});
3. option-keyboard.js
// option-keyboard.js
document.addEventListener('DOMContentLoaded', () => {
// 键盘事件监听
document.addEventListener('keydown', (e) => {
// 只处理A、B、C、D键(不区分大小写)
const key = e.key.toUpperCase();
if (['A', 'B', 'C', 'D'].includes(key)) {
const optionsContainer = document.getElementById('options-container');
// 检查选项容器是否可见(quiz-panel可见且options-container有内容)
if (optionsContainer &&
!document.getElementById('quiz-panel').classList.contains('hidden') &&
optionsContainer.children.length > 0) {
// 根据按键确定选项索引
const optionIndex = key.charCodeAt(0) - 'A'.charCodeAt(0);
const options = optionsContainer.children;
// 检查索引是否有效
if (optionIndex >= 0 && optionIndex < options.length) {
// 模拟点击对应的选项
options[optionIndex].click();
// 添加视觉反馈
options[optionIndex].classList.add('keyboard-selected');
setTimeout(() => {
options[optionIndex].classList.remove('keyboard-selected');
}, 200);
}
}
}
});
});
4. html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>题库系统</title>
<script src="keyboard-control.js"></script>
<script src="option-keyboard.js"></script>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="setup-panel">
<label for="quiz-select">选择题库:</label>
<select id="quiz-select"></select>
<button onclick="startQuiz()">开始答题</button>
</div>
<div id="quiz-panel" class="hidden">
<button onclick="exitQuiz()" style="float: right">退出答题</button>
<h2 id="quiz-name"></h2>
<div class="stats">
正确:<span id="correct-count">0</span> |
错误:<span id="wrong-count">0</span> |
当前:<span id="question-num">0</span>/<span id="total-questions">0</span>
</div>
<h3 id="question-title"></h3>
<div id="options-container"></div>
<div class="analysis hidden" id="analysis"></div>
<button id="next-btn" class="hidden" onclick="goToNextQuestion()">下一题</button>
</div>
<script>
// 可用题库列表(需手动维护)
const availableQuizzes = ['questionBase.json', '题库A.json', 'test.json', '题库B.json'];
// 从localStorage读取进度
const progress = JSON.parse(localStorage.getItem('quizProgress') || '{ "currentIndex": 0, "answers": {} }');
// 初始化题库选择器
function initQuizSelector() {
const select = document.getElementById('quiz-select');
availableQuizzes.forEach(file => {
const option = document.createElement('option');
option.value = file;
option.textContent = file;
select.appendChild(option);
});
// 默认选中questionBase.json
select.value = 'questionBase.json';
}
// 开始答题
async function startQuiz() {
const selectedFile = document.getElementById('quiz-select').value;
const response = await fetch(selectedFile);
const data = await response.json();
// 保存当前题库状态
localStorage.setItem('currentQuiz', JSON.stringify({
file: selectedFile,
name: data.name || selectedFile,
questions: data.data,
progress: { currentIndex: 0, answers: {} }
}));
// 切换面板
document.getElementById('setup-panel').classList.add('hidden');
document.getElementById('quiz-panel').classList.remove('hidden');
// 初始化统计信息
updateStats(1, 0, 0, data.data.length);
// 渲染第一题
renderQuestion(data.data, 0);
}
// 退出答题
async function exitQuiz() {
// const selectedFile = document.getElementById('quiz-select').value;
// const response = await fetch(selectedFile);
// const data = await response.json();
// // 保存当前题库状态
// localStorage.setItem('currentQuiz', JSON.stringify({
// file: selectedFile,
// name: data.name || selectedFile,
// questions: data.data,
// progress: { currentIndex: 0, answers: {} }
// }));
// 切换面板
document.getElementById('setup-panel').classList.remove('hidden');
document.getElementById('quiz-panel').classList.add('hidden');
// // 初始化统计信息
// updateStats(1, 0, 0, data.data.length);
// // 渲染第一题
// renderQuestion(data.data, 0);
}
// 新增下一题逻辑
function goToNextQuestion() {
const currentQuiz = JSON.parse(localStorage.getItem('currentQuiz'));
const progress = currentQuiz.progress;
// 检查是否已经是最后一题
if (progress.currentIndex >= currentQuiz.questions.length - 1) {
// 如果是最后一题,直接渲染完成状态
renderQuestion(currentQuiz.questions, currentQuiz.questions.length);
return;
}
progress.currentIndex++;
// 计算正确/错误数
let correct = Object.values(progress.answers).filter((ans, i) =>
ans === currentQuiz.questions[i].answer.type
).length;
let wrong = Object.keys(progress.answers).length - correct;
// 更新统计信息
updateStats(
progress.currentIndex, // 这里改为使用更新后的currentIndex
correct,
wrong,
currentQuiz.questions.length
);
localStorage.setItem('currentQuiz', JSON.stringify({
...currentQuiz,
progress: progress
}));
document.getElementById('next-btn').classList.add('hidden');
document.getElementById('analysis').classList.add('hidden');
renderQuestion(currentQuiz.questions, progress.currentIndex);
}
// 渲染题目
function renderQuestion(questions, index) {
document.getElementById('next-btn').classList.add('hidden');
document.getElementById('analysis').classList.add('hidden');
if (index >= questions.length) {
document.getElementById('question-title').textContent = '已完成所有题目!';
document.getElementById('options-container').innerHTML = `
<button onclick="restartQuiz()">重新选择题库</button>
`;
document.getElementById('analysis').textContent = '';
return;
}
const question = questions[index];
document.getElementById('question-title').textContent = question.title;
// if (index == 0) {
// // 更新题号统计
// updateStats(index + 1, 0, 0, questions.length);
// }
const optionsHtml = question.options.map((opt, i) => `
<div class="option ${progress.answers[index] === opt.type ? 'active' : ''}"
onclick="handleAnswer('${opt.type}', ${index}, ${question.answer.type === opt.type})">
${opt.type}: ${opt.content}
</div>
`).join('');
document.getElementById('options-container').innerHTML = optionsHtml;
document.getElementById('analysis').textContent =
progress.answers[index] ? `答案:选项${question.answer.type} | ${question.analysis}` : '';
}
// 处理答题逻辑
window.handleAnswer = (selectedOption, index, isCorrect) => {
const currentQuiz = JSON.parse(localStorage.getItem('currentQuiz'));
const progress = currentQuiz.progress;
progress.answers[index] = selectedOption;
// 计算正确/错误数
let correct = Object.values(progress.answers).filter((ans, i) =>
ans === currentQuiz.questions[i].answer.type
).length;
let wrong = Object.keys(progress.answers).length - correct;
// 更新统计信息
updateStats(index + 1, correct, wrong, currentQuiz.questions.length);
// 保存进度
localStorage.setItem('currentQuiz', JSON.stringify({
...currentQuiz,
progress: {
...progress,
answers: progress.answers
}
}));
// 显示解析并自动切换下一题
setTimeout(() => {
if (selectedOption != currentQuiz.questions[index].answer.type) {
document.getElementById('analysis').classList.add('analysis-error');
} else {
document.getElementById('analysis').classList.remove('analysis-error');
}
document.getElementById('analysis').textContent =
`你的选择:${selectedOption} | 正确答案:${currentQuiz.questions[index].answer.type} | ${currentQuiz.questions[index].analysis}`;
document.getElementById('next-btn').classList.remove('hidden');
document.getElementById('analysis').classList.remove('hidden');
let a = progress.currentIndex;
// setTimeout(() => {
// // progress.currentIndex = index + 1;
// // localStorage.setItem('currentQuiz', JSON.stringify({
// // ...currentQuiz,
// // progress: progress
// // }));
// // renderQuestion(currentQuiz.questions, progress.currentIndex);
// }, 5500);
}, 500);
}
// 更新统计信息
function updateStats(questionNum, correct, wrong, total) {
document.getElementById('question-num').textContent = questionNum;
document.getElementById('total-questions').textContent = total;
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('quiz-name').textContent = JSON.parse(localStorage.getItem('currentQuiz'))?.name || '题库';
}
// 重新开始
function restartQuiz() {
document.getElementById('quiz-panel').classList.add('hidden');
document.getElementById('setup-panel').classList.remove('hidden');
localStorage.removeItem('currentQuiz');
}
// 页面初始化
document.addEventListener('DOMContentLoaded', () => {
initQuizSelector();
// 检查是否有未完成的答题进度
const savedQuiz = localStorage.getItem('currentQuiz');
if (savedQuiz) {
const quizData = JSON.parse(savedQuiz);
document.getElementById('quiz-select').value = quizData.file;
document.getElementById('setup-panel').classList.add('hidden');
document.getElementById('quiz-panel').classList.remove('hidden');
// 从上次进度继续
const progress = quizData.progress;
renderQuestion(quizData.questions, progress.currentIndex);
updateStats(
progress.currentIndex + 1,
Object.values(progress.answers).filter((ans, i) =>
ans === quizData.questions[i].answer.type
).length,
progress.correct != undefined ? Object.keys(progress.answers).length - progress.correct : Object.keys(progress.answers).length,
quizData.questions.length
);
}
});
</script>
</body>
</html>

浙公网安备 33010602011771号