自己考试要刷题,没有什么好的就自己让AI写了一个用着还行,主要功能就是导入题库Excel,格式是(题干、答案、选项、选项A、选项B、选项C、选项D、选项E、解析),可以导入多个题库,进行切换,保存进度啥的。只写了选择题,判断题应该也能按选择题来。手机浏览器,电脑浏览器应该都能用。也能通过其他软件打包成apk到手机使用,
<!DOCTYPE html>
<html lang=”zh-CN”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1.0″>
<title>智能题库系统</title>
<style>
:root {
–correct-color: #4CAF50;
–wrong-color: #f44336;
–primary-color: #2196F3;
–light-bg: #f5f5f5;
–dark-bg: #333;
}
复制代码 隐藏代码
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
margin: 0;
padding: 0;
background-color: var(--light-bg);
color: #333;
line-height: 1.6;
}
#app {
max-width: 1000px;
margin: 0 auto;
padding: 20px;
background-color: white;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
min-height: 100vh;
}
#header {
background-color: var(--dark-bg);
color: white;
padding: 15px 20px;
border-radius: 5px 5px 0 0;
margin-bottom: 20px;
}
#nav {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 20px;
padding: 15px;
background-color: white;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
#library-manager {
margin-bottom: 20px;
padding: 15px;
background-color: white;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
#library-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.library-item {
padding: 8px 15px;
background-color: var(--light-bg);
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
}
.library-item:hover {
background-color: #e0e0e0;
}
.library-item.active {
background-color: var(--primary-color);
color: white;
}
#progress-container {
margin-bottom: 20px;
}
#progress-bar {
height: 10px;
background-color: #e0e0e0;
border-radius: 5px;
overflow: hidden;
}
#progress {
height: 100%;
background-color: var(--primary-color);
width: 0%;
transition: width 0.3s;
}
#question-container {
background-color: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
#question {
font-size: 1.2em;
margin-bottom: 20px;
font-weight: bold;
}
.option {
display: flex;
align-items: center;
width: 100%;
padding: 12px 15px;
margin: 8px 0;
background-color: var(--light-bg);
border: none;
border-left: 4px solid transparent;
border-radius: 4px;
text-align: left;
cursor: pointer;
transition: all 0.2s;
}
.option:hover {
background-color: #e0e0e0;
}
.option-letter {
display: inline-block;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
background-color: #ddd;
border-radius: 50%;
margin-right: 10px;
font-weight: bold;
}
/* 正确答案样式 - 绿色 */
.correct-answer {
background-color: #e8f5e9 !important;
border-left-color: var(--correct-color) !important;
color: #2e7d32;
}
.correct-answer .option-letter {
background-color: var(--correct-color);
color: white;
}
/* 用户选择的错误答案 - 红色 */
.wrong-answer {
background-color: #ffebee !important;
border-left-color: var(--wrong-color) !important;
color: #c62828;
}
.wrong-answer .option-letter {
background-color: var(--wrong-color);
color: white;
}
/* 背题模式下的选项样式 */
.back-mode-option {
background-color: white;
cursor: default;
}
#answer-container {
margin-top: 20px;
padding: 15px;
background-color: #e8f5e9;
border-radius: 5px;
border-left: 4px solid var(--correct-color);
}
#explanation-container {
margin-top: 15px;
padding: 15px;
background-color: #e3f2fd;
border-radius: 5px;
border-left: 4px solid var(--primary-color);
}
.button {
padding: 10px 20px;
border: none;
border-radius: 4px;
font-weight: bold;
cursor: pointer;
transition: all 0.2s;
}
.button-primary {
background-color: var(--primary-color);
color: white;
}
.button-success {
background-color: var(--correct-color);
color: white;
}
.button-danger {
background-color: var(--wrong-color);
color: white;
}
.button-warning {
background-color: #FF9800;
color: white;
}
#navigation {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
#status-info {
margin-bottom: 15px;
font-size: 0.9em;
color: #666;
}
input[type="number"] {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
width: 60px;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div id=”app”>
<div id=”header”>
<h1>智能题库系统</h1>
</div>
复制代码 隐藏代码
<div id="library-manager">
<div>
<input type="file" id="fileInput" class="hidden" accept=".xlsx,.xls">
<button id="importButton" class="button button-success">导入新题库</button>
<button id="deleteLibraryButton" class="button button-danger">删除当前题库</button>
<button id="resetLibraryButton" class="button button-warning">重置题库</button>
</div>
<div id="library-list"></div>
</div>
<div id="nav">
<button id="modeButton" class="button button-warning">切换模式</button>
<button id="shuffleButton" class="button button-primary">乱序练习</button>
<input type="number" id="jumpInput" placeholder="题号" min="1">
<button id="jumpButton" class="button button-primary">跳转</button>
</div>
<div id="progress-container">
<div id="status-info"></div>
<div id="progress-bar">
<div id="progress"></div>
</div>
</div>
<div id="question-container">
<div id="question"></div>
<div id="options"></div>
<div id="answer-container" class="hidden">
<strong>正确答案:</strong><span id="correct-answer"></span>
</div>
<div id="explanation-container" class="hidden">
<strong>解析:</strong><span id="explanation"></span>
</div>
</div>
<div id="navigation">
<button id="prevButton" class="button button-primary">上一题</button>
<button id="nextButton" class="button button-primary">下一题</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
// 题库应用
const quizApp = {
data: {
libraries: [], // 所有题库
currentLibraryIndex: 0, // 当前题库索引
currentIndex: 0, // 当前题目索引
mode: 'practice', // 'practice' 或 'back'
isShuffled: false
},
// 初始化应用
init() {
this.loadFromStorage();
this.setupEventListeners();
this.updateUI();
},
// 从本地存储加载数据
loadFromStorage() {
const savedData = localStorage.getItem('quizData');
if (savedData) {
this.data = JSON.parse(savedData);
}
// 如果没有题库,初始化一个空数组
if (!this.data.libraries) {
this.data.libraries = [];
this.data.currentLibraryIndex = 0;
}
},
// 保存数据到本地存储
saveToStorage() {
localStorage.setItem('quizData', JSON.stringify(this.data));
},
// 设置事件监听器
setupEventListeners() {
// 导入题库
document.getElementById('importButton').addEventListener('click', () => {
document.getElementById('fileInput').click();
});
document.getElementById('fileInput').addEventListener('change', (e) => {
this.importLibrary(e.target.files[0]);
e.target.value = ''; // 重置文件输入
});
// 删除当前题库
document.getElementById('deleteLibraryButton').addEventListener('click', () => {
if (this.data.libraries.length === 0) {
alert('没有可删除的题库');
return;
}
if (confirm(`确定要删除题库 "${this.getCurrentLibrary().name}" 吗?`)) {
this.data.libraries.splice(this.data.currentLibraryIndex, 1);
// 调整当前题库索引
if (this.data.currentLibraryIndex >= this.data.libraries.length) {
this.data.currentLibraryIndex = Math.max(0, this.data.libraries.length - 1);
}
// 如果没有题库了,重置状态
if (this.data.libraries.length === 0) {
this.data.currentIndex = 0;
this.data.mode = 'practice';
this.data.isShuffled = false;
}
this.saveToStorage();
this.updateUI();
}
});
// 切换模式
document.getElementById('modeButton').addEventListener('click', () => {
this.data.mode = this.data.mode === 'practice' ? 'back' : 'practice';
this.saveToStorage();
this.updateUI();
});
// 乱序练习
document.getElementById('shuffleButton').addEventListener('click', () => {
this.toggleShuffle();
});
// 跳转题目
document.getElementById('jumpButton').addEventListener('click', () => {
this.jumpToQuestion();
});
// 导航按钮
document.getElementById('prevButton').addEventListener('click', () => {
this.prevQuestion();
});
document.getElementById('nextButton').addEventListener('click', () => {
this.nextQuestion();
});
// 重置题库
document.getElementById('resetLibraryButton').addEventListener('click', () => {
this.resetLibrary();
});
},
// 获取当前题库
getCurrentLibrary() {
return this.data.libraries[this.data.currentLibraryIndex] || {
name: '未命名题库',
questions: [],
userAnswers: {},
originalOrder: []
};
},
// 获取当前题目
getCurrentQuestion() {
const library = this.getCurrentLibrary();
return library.questions[this.data.currentIndex] || {};
},
// 导入题库
importLibrary(file) {
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
try {
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, { type: 'array' });
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
// 创建新题库
const newLibrary = {
name: file.name.replace(/\.[^/.]+$/, ""), // 去除文件扩展名
questions: jsonData.map(row => ({
题干: row[0] || '',
答案: (row[1] || '').toString().trim().toUpperCase(), // 确保答案为单个大写字母
选项A: row[2] || '',
选项B: row[3] || '',
选项C: row[4] || '',
选项D: row[5] || '',
选项E: row[6] || '',
解析: row[7] || ''
})).filter(q => q.题干), // 过滤掉空题目
userAnswers: {},
originalOrder: []
};
// 添加到题库列表
this.data.libraries.push(newLibrary);
this.data.currentLibraryIndex = this.data.libraries.length - 1;
this.data.currentIndex = 0;
this.saveToStorage();
this.updateUI();
} catch (error) {
alert('导入失败,请检查文件格式是否正确');
console.error(error);
}
};
reader.readAsArrayBuffer(file);
},
// 切换题库
switchLibrary(index) {
if (index >= 0 && index < this.data.libraries.length) {
this.data.currentLibraryIndex = index;
this.data.currentIndex = 0;
this.saveToStorage();
this.updateUI();
}
},
// 切换乱序/顺序
toggleShuffle() {
const library = this.getCurrentLibrary();
if (library.questions.length === 0) {
alert('当前题库没有题目');
return;
}
if (!this.data.isShuffled) {
// 保存原始顺序
library.originalOrder = library.questions.map((_, i) => i);
// 创建并打乱新顺序
const shuffledIndices = [...library.originalOrder];
for (let i = shuffledIndices.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledIndices[i], shuffledIndices[j]] = [shuffledIndices[j], shuffledIndices[i]];
}
// 重新排序问题和用户答案
library.questions = shuffledIndices.map(i => library.questions[i]);
const newUserAnswers = {};
Object.keys(library.userAnswers).forEach(key => {
const originalIndex = parseInt(key);
const newIndex = shuffledIndices.indexOf(originalIndex);
if (newIndex !== -1) {
newUserAnswers[newIndex] = library.userAnswers[originalIndex];
}
});
library.userAnswers = newUserAnswers;
this.data.currentIndex = 0;
} else {
// 恢复原始顺序
const newQuestions = library.originalOrder.map(i => library.questions[i]);
const newUserAnswers = {};
Object.keys(library.userAnswers).forEach(key => {
const shuffledIndex = parseInt(key);
const originalIndex = library.originalOrder[shuffledIndex];
newUserAnswers[originalIndex] = library.userAnswers[shuffledIndex];
});
library.questions = newQuestions;
library.userAnswers = newUserAnswers;
this.data.currentIndex = library.originalOrder.indexOf(this.data.currentIndex);
if (this.data.currentIndex === -1) this.data.currentIndex = 0;
}
this.data.isShuffled = !this.data.isShuffled;
this.saveToStorage();
this.updateUI();
},
// 跳转到指定题目
jumpToQuestion() {
const input = document.getElementById('jumpInput');
const jumpTo = parseInt(input.value) - 1;
const library = this.getCurrentLibrary();
if (!isNaN(jumpTo) && jumpTo >= 0 && jumpTo < library.questions.length) {
this.data.currentIndex = jumpTo;
this.saveToStorage();
this.updateUI();
} else {
alert(`请输入1-${library.questions.length}之间的有效题号`);
input.value = this.data.currentIndex + 1;
}
},
// 上一题
prevQuestion() {
const library = this.getCurrentLibrary();
if (this.data.currentIndex > 0) {
this.data.currentIndex--;
this.saveToStorage();
this.updateUI();
} else {
alert('已经是第一题了');
}
},
// 下一题
nextQuestion() {
const library = this.getCurrentLibrary();
if (this.data.currentIndex < library.questions.length - 1) {
this.data.currentIndex++;
this.saveToStorage();
this.updateUI();
} else {
alert('已经是最后一题了');
}
},
// 选择选项
selectOption(optionLetter) {
if (this.data.mode !== 'practice') return;
const currentQuestion = this.getCurrentQuestion();
const isCorrect = optionLetter === currentQuestion.答案;
const library = this.getCurrentLibrary();
library.userAnswers[this.data.currentIndex] = {
selected: optionLetter,
isCorrect: isCorrect
};
this.saveToStorage();
this.updateOptionStyles(); // 更新选项样式
this.renderAnswerAndExplanation(); // 立即显示答案解析
},
// 更新选项样式
updateOptionStyles() {
const currentQuestion = this.getCurrentQuestion();
const library = this.getCurrentLibrary();
const userAnswer = library.userAnswers[this.data.currentIndex];
const options = document.querySelectorAll('.option');
options.forEach(option => {
// 重置所有选项样式
option.classList.remove('correct-answer', 'wrong-answer');
// 获取选项对应的字母(A/B/C/D/E)
const optionLetter = option.querySelector('.option-letter').textContent.trim();
// 1. 背题模式下显示所有正确答案
if (this.data.mode === 'back' && optionLetter === currentQuestion.答案) {
option.classList.add('correct-answer');
}
// 2. 练习模式下只显示用户选择的答案
if (this.data.mode === 'practice' && userAnswer) {
// 正确答案(绿色)
if (optionLetter === currentQuestion.答案) {
option.classList.add('correct-answer');
}
// 用户选错的选项(红色)
if (userAnswer.selected === optionLetter && !userAnswer.isCorrect) {
option.classList.add('wrong-answer');
}
}
});
},
// 渲染题目
renderQuestion() {
const question = this.getCurrentQuestion();
const optionsContainer = document.getElementById('options');
optionsContainer.innerHTML = '';
// 显示题目
document.getElementById('question').textContent = question.题干 || '暂无题目';
// 显示选项(A-E)
const optionLetters = ['A', 'B', 'C', 'D', 'E'];
optionLetters.forEach((letter, index) => {
const optionKey = `选项${letter}`;
if (question[optionKey]) {
const option = document.createElement('button');
option.className = 'option';
option.innerHTML = `
<span class="option-letter">${letter}</span>
<span class="option-text">${question[optionKey]}</span>
`;
if (this.data.mode === 'back') {
option.classList.add('back-mode-option');
} else {
// 直接传递字母(A/B/C/D/E)给selectOption
option.addEventListener('click', () => this.selectOption(letter));
}
optionsContainer.appendChild(option);
}
});
this.updateOptionStyles();
},
// 渲染答案和解析
renderAnswerAndExplanation() {
const question = this.getCurrentQuestion();
const answerContainer = document.getElementById('answer-container');
const explanationContainer = document.getElementById('explanation-container');
const library = this.getCurrentLibrary();
const userAnswer = library.userAnswers[this.data.currentIndex];
// 显示正确答案的字母
document.getElementById('correct-answer').textContent = question.答案 || '暂无答案';
document.getElementById('explanation').textContent = question.解析 || '暂无解析';
// 背题模式始终显示答案和解析
if (this.data.mode === 'back') {
answerContainer.classList.remove('hidden');
explanationContainer.classList.remove('hidden');
return;
}
// 练习模式 - 只在用户选择后显示
if (userAnswer) {
answerContainer.classList.remove('hidden');
explanationContainer.classList.remove('hidden');
} else {
answerContainer.classList.add('hidden');
explanationContainer.classList.add('hidden');
}
},
// 更新UI
updateUI() {
this.updateLibraryList();
this.updateProgress();
this.updateStatusInfo();
this.renderQuestion();
this.updateButtonStates();
this.renderAnswerAndExplanation();
},
// 更新题库列表
updateLibraryList() {
const libraryList = document.getElementById('library-list');
libraryList.innerHTML = '';
this.data.libraries.forEach((library, index) => {
const libraryItem = document.createElement('div');
libraryItem.className = 'library-item';
if (index === this.data.currentLibraryIndex) {
libraryItem.classList.add('active');
}
libraryItem.textContent = library.name;
libraryItem.addEventListener('click', () => this.switchLibrary(index));
libraryList.appendChild(libraryItem);
});
},
// 更新进度条
updateProgress() {
const library = this.getCurrentLibrary();
const progress = library.questions.length > 0
? ((this.data.currentIndex + 1) / library.questions.length) * 100
: 0;
document.getElementById('progress').style.width = `${progress}%`;
},
// 更新状态信息
updateStatusInfo() {
const library = this.getCurrentLibrary();
if (library.questions.length === 0) {
document.getElementById('status-info').textContent = '当前题库没有题目';
return;
}
const statusText = `共 ${library.questions.length} 题 | 第 ${this.data.currentIndex + 1} 题 | ${this.data.mode === 'practice' ? '练习模式' : '背题模式'} | ${this.data.isShuffled ? '乱序' : '顺序'}`;
document.getElementById('status-info').textContent = statusText;
document.getElementById('shuffleButton').textContent = this.data.isShuffled ? '顺序练习' : '乱序练习';
document.getElementById('modeButton').textContent = this.data.mode === 'practice' ? '切换到背题模式' : '切换到练习模式';
},
// 更新按钮状态
updateButtonStates() {
const library = this.getCurrentLibrary();
const hasQuestions = library.questions.length > 0;
document.getElementById('prevButton').disabled = this.data.currentIndex === 0 || !hasQuestions;
document.getElementById('nextButton').disabled =
this.data.currentIndex === library.questions.length - 1 || !hasQuestions;
document.getElementById('modeButton').disabled = !hasQuestions;
document.getElementById('shuffleButton').disabled = !hasQuestions;
document.getElementById('jumpButton').disabled = !hasQuestions;
document.getElementById('jumpInput').disabled = !hasQuestions;
// 更新跳转输入框的值
if (hasQuestions) {
document.getElementById('jumpInput').value = this.data.currentIndex + 1;
document.getElementById('jumpInput').max = library.questions.length;
} else {
document.getElementById('jumpInput').value = '';
}
},
// 重置题库
resetLibrary() {
if (this.data.libraries.length === 0) {
alert('没有可重置的题库');
return;
}
const currentLibrary = this.getCurrentLibrary();
if (!currentLibrary.name || currentLibrary.questions.length === 0) {
alert('当前题库没有题目可重置');
return;
}
if (confirm(`确定要重置题库 "${currentLibrary.name}" 吗?这将清除所有用户答案并恢复到初始状态。`)) {
// 创建一个新的题库副本,不包含userAnswers和originalOrder
const originalLibrary = JSON.parse(JSON.stringify(this.data.libraries[this.data.currentLibraryIndex]));
delete originalLibrary.userAnswers;
delete originalLibrary.originalOrder;
// 如果没有原始数据,则创建一个新的"干净"副本
this.data.libraries[this.data.currentLibraryIndex] = {
name: originalLibrary.name,
questions: JSON.parse(JSON.stringify(originalLibrary.questions)), // 深拷贝题目
userAnswers: {}, // 清空用户答案
originalOrder: [] // 重置原始顺序
};
// 重置当前题目索引和模式
this.data.currentIndex = 0;
this.data.mode = 'practice';
this.data.isShuffled = false;
// 更新UI
this.saveToStorage();
this.updateUI();
alert('题库已重置');
}
},
// 切换乱序/顺序
toggleShuffle() {
const library = this.getCurrentLibrary();
if (library.questions.length === 0) {
alert('当前题库没有题目');
return;
}
if (!this.data.isShuffled) {
// 保存原始顺序
library.originalOrder = library.questions.map((_, i) => i);
// 创建并打乱新顺序
const shuffledIndices = [...library.originalOrder];
for (let i = shuffledIndices.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledIndices[i], shuffledIndices[j]] = [shuffledIndices[j], shuffledIndices[i]];
}
// 重新排序问题和用户答案
library.questions = shuffledIndices.map(i => library.questions[i]);
const newUserAnswers = {};
Object.keys(library.userAnswers).forEach(key => {
const originalIndex = parseInt(key);
const newIndex = shuffledIndices.indexOf(originalIndex);
if (newIndex !== -1) {
newUserAnswers[newIndex] = library.userAnswers[originalIndex];
}
});
library.userAnswers = newUserAnswers;
this.data.currentIndex = 0;
} else {
// 恢复原始顺序
const newQuestions = library.originalOrder.map(i => library.questions[i]);
const newUserAnswers = {};
Object.keys(library.userAnswers).forEach(key => {
const shuffledIndex = parseInt(key);
const originalIndex = library.originalOrder[shuffledIndex];
newUserAnswers[originalIndex] = library.userAnswers[shuffledIndex];
});
library.questions = newQuestions;
library.userAnswers = newUserAnswers;
this.data.currentIndex = library.originalOrder.indexOf(this.data.currentIndex);
if (this.data.currentIndex === -1) this.data.currentIndex = 0;
}
this.data.isShuffled = !this.data.isShuffled;
this.saveToStorage();
this.updateUI();
},
// 跳转到指定题目
jumpToQuestion() {
const input = document.getElementById('jumpInput');
const jumpTo = parseInt(input.value) - 1;
const library = this.getCurrentLibrary();
if (!isNaN(jumpTo) && jumpTo >= 0 && jumpTo < library.questions.length) {
this.data.currentIndex = jumpTo;
this.saveToStorage();
this.updateUI();
} else {
alert(`请输入1-${library.questions.length}之间的有效题号`);
input.value = this.data.currentIndex + 1;
}
},
// 上一题
prevQuestion() {
const library = this.getCurrentLibrary();
if (this.data.currentIndex > 0) {
this.data.currentIndex--;
this.saveToStorage();
this.updateUI();
} else {
alert('已经是第一题了');
}
},
// 下一题
nextQuestion() {
const library = this.getCurrentLibrary();
if (this.data.currentIndex < library.questions.length - 1) {
this.data.currentIndex++;
this.saveToStorage();
this.updateUI();
} else {
alert('已经是最后一题了');
}
},
// 选择选项
selectOption(optionLetter) {
if (this.data.mode !== 'practice') return;
const currentQuestion = this.getCurrentQuestion();
const isCorrect = optionLetter === currentQuestion.答案;
const library = this.getCurrentLibrary();
// 保存用户选择
library.userAnswers[this.data.currentIndex] = {
selected: optionLetter,
isCorrect: isCorrect
};
this.saveToStorage();
this.updateOptionStyles(); // 更新选项样式
this.renderAnswerAndExplanation(); // 立即显示答案解析
}
};
// 初始化应用
document.addEventListener('DOMContentLoaded', () => {
quizApp.init();
});
</script>
</body>
</html>
有魔改好用的吱一声让我也用用
还有很多不好的地方,比如乱序模式点重置后题目还是乱序的,没有从一开始了,解决办法就是删了重新导入
扫码免费获取资源:
