672 lines
21 KiB
HTML
672 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>AI智能游戏生成器 - 融光课堂</title>
|
||
<link rel="stylesheet" href="../css/indexDetail.css" />
|
||
<link rel="stylesheet" href="../css/userDisplay.css" />
|
||
<style>
|
||
.ai-generator-container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 20px;
|
||
}
|
||
|
||
.generator-header {
|
||
text-align: center;
|
||
margin-bottom: 30px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 30px;
|
||
border-radius: 15px;
|
||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.generator-header h1 {
|
||
font-size: 2.5em;
|
||
margin-bottom: 10px;
|
||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
|
||
}
|
||
|
||
.generator-header p {
|
||
font-size: 1.2em;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.generator-content {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 30px;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.generator-panel {
|
||
background: white;
|
||
border-radius: 15px;
|
||
padding: 25px;
|
||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
|
||
border: 1px solid #e0e0e0;
|
||
}
|
||
|
||
.panel-title {
|
||
font-size: 1.5em;
|
||
font-weight: bold;
|
||
margin-bottom: 20px;
|
||
color: #333;
|
||
border-bottom: 2px solid #667eea;
|
||
padding-bottom: 10px;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.form-label {
|
||
display: block;
|
||
margin-bottom: 8px;
|
||
font-weight: 600;
|
||
color: #555;
|
||
}
|
||
|
||
.form-select,
|
||
.form-input {
|
||
width: 100%;
|
||
padding: 12px;
|
||
border: 2px solid #e0e0e0;
|
||
border-radius: 8px;
|
||
font-size: 16px;
|
||
transition: border-color 0.3s;
|
||
}
|
||
|
||
.form-select:focus,
|
||
.form-input:focus {
|
||
outline: none;
|
||
border-color: #667eea;
|
||
}
|
||
|
||
.difficulty-slider {
|
||
width: 100%;
|
||
margin: 10px 0;
|
||
}
|
||
|
||
.difficulty-labels {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
font-size: 0.9em;
|
||
color: #666;
|
||
}
|
||
|
||
.generate-btn {
|
||
width: 100%;
|
||
padding: 15px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 10px;
|
||
font-size: 1.1em;
|
||
font-weight: bold;
|
||
cursor: pointer;
|
||
transition: transform 0.2s, box-shadow 0.2s;
|
||
}
|
||
|
||
.generate-btn:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
|
||
}
|
||
|
||
.generate-btn:disabled {
|
||
opacity: 0.6;
|
||
cursor: not-allowed;
|
||
transform: none;
|
||
}
|
||
|
||
.game-preview {
|
||
background: #f8f9fa;
|
||
border-radius: 10px;
|
||
padding: 20px;
|
||
margin-top: 20px;
|
||
min-height: 200px;
|
||
}
|
||
|
||
.question-item {
|
||
background: white;
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
margin-bottom: 15px;
|
||
border-left: 4px solid #667eea;
|
||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.question-text {
|
||
font-weight: 600;
|
||
margin-bottom: 10px;
|
||
color: #333;
|
||
}
|
||
|
||
.question-options {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 8px;
|
||
}
|
||
|
||
.option-item {
|
||
background: #e9ecef;
|
||
padding: 8px 12px;
|
||
border-radius: 5px;
|
||
text-align: center;
|
||
font-size: 0.9em;
|
||
}
|
||
|
||
.stats-panel {
|
||
grid-column: 1 / -1;
|
||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||
color: white;
|
||
}
|
||
|
||
.stats-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||
gap: 20px;
|
||
}
|
||
|
||
.stat-item {
|
||
text-align: center;
|
||
padding: 15px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
border-radius: 10px;
|
||
backdrop-filter: blur(10px);
|
||
}
|
||
|
||
.stat-value {
|
||
font-size: 2em;
|
||
font-weight: bold;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: 0.9em;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.loading {
|
||
text-align: center;
|
||
padding: 40px;
|
||
color: #666;
|
||
}
|
||
|
||
.loading-spinner {
|
||
width: 40px;
|
||
height: 40px;
|
||
border: 4px solid #f3f3f3;
|
||
border-top: 4px solid #667eea;
|
||
border-radius: 50%;
|
||
animation: spin 1s linear infinite;
|
||
margin: 0 auto 20px;
|
||
}
|
||
|
||
@keyframes spin {
|
||
0% {
|
||
transform: rotate(0deg);
|
||
}
|
||
100% {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.error-message {
|
||
background: #ffebee;
|
||
color: #c62828;
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
margin: 15px 0;
|
||
border-left: 4px solid #c62828;
|
||
}
|
||
|
||
.success-message {
|
||
background: #e8f5e8;
|
||
color: #2e7d32;
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
margin: 15px 0;
|
||
border-left: 4px solid #2e7d32;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.generator-content {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.generator-header h1 {
|
||
font-size: 2em;
|
||
}
|
||
|
||
.question-options {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<!-- 导航条 -->
|
||
<div class="container-header">
|
||
<div class="container-header-logo">
|
||
<img src="../asset/logo.png" alt="logo" />
|
||
</div>
|
||
<nav class="container-header-nav">
|
||
<div data-url="indexHome">首页</div>
|
||
<div data-url="indexDetail">导航</div>
|
||
<div data-url="courseHome">课程</div>
|
||
<div data-url="student_analytics">数据分析</div>
|
||
<div class="active" data-url="ai_game_generator">AI游戏生成器</div>
|
||
</nav>
|
||
<div id="userDisplay" class="user-display"></div>
|
||
</div>
|
||
|
||
<!-- AI游戏生成器内容 -->
|
||
<div class="ai-generator-container">
|
||
<div class="generator-header">
|
||
<h1>🤖 AI智能游戏生成器</h1>
|
||
<p>
|
||
基于学习进度自动生成个性化游戏,智能调整难度,为每个学生定制专属学习体验
|
||
</p>
|
||
</div>
|
||
|
||
<div class="generator-content">
|
||
<!-- 游戏配置面板 -->
|
||
<div class="generator-panel">
|
||
<div class="panel-title">🎮 游戏配置</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">学科选择</label>
|
||
<select class="form-select" id="subjectSelect">
|
||
<option value="math">数学</option>
|
||
<option value="language">语文</option>
|
||
<option value="life">生活</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">游戏类型</label>
|
||
<select class="form-select" id="gameTypeSelect">
|
||
<option value="quiz">选择题游戏</option>
|
||
<option value="matching">配对游戏</option>
|
||
<option value="puzzle">拼图游戏</option>
|
||
<option value="memory">记忆游戏</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label">题目数量</label>
|
||
<select class="form-select" id="questionCountSelect">
|
||
<option value="3">3题</option>
|
||
<option value="5" selected>5题</option>
|
||
<option value="8">8题</option>
|
||
<option value="10">10题</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label"
|
||
>难度等级: <span id="difficultyValue">1</span></label
|
||
>
|
||
<input
|
||
type="range"
|
||
class="difficulty-slider"
|
||
id="difficultySlider"
|
||
min="1"
|
||
max="5"
|
||
value="1"
|
||
/>
|
||
<div class="difficulty-labels">
|
||
<span>简单</span>
|
||
<span>中等</span>
|
||
<span>困难</span>
|
||
</div>
|
||
</div>
|
||
|
||
<button
|
||
class="generate-btn"
|
||
id="generateBtn"
|
||
onclick="generateGame()"
|
||
>
|
||
🚀 生成个性化游戏
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 游戏预览面板 -->
|
||
<div class="generator-panel">
|
||
<div class="panel-title">👀 游戏预览</div>
|
||
<div id="gamePreview" class="game-preview">
|
||
<div class="loading">
|
||
<div class="loading-spinner"></div>
|
||
<p>点击"生成个性化游戏"开始创建</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 统计面板 -->
|
||
<div class="generator-panel stats-panel">
|
||
<div class="panel-title">📊 学习统计</div>
|
||
<div class="stats-grid" id="statsGrid">
|
||
<div class="stat-item">
|
||
<div class="stat-value" id="currentDifficulty">1</div>
|
||
<div class="stat-label">当前难度</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value" id="totalGames">0</div>
|
||
<div class="stat-label">总游戏数</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value" id="successRate">0%</div>
|
||
<div class="stat-label">成功率</div>
|
||
</div>
|
||
<div class="stat-item">
|
||
<div class="stat-value" id="avgTime">0s</div>
|
||
<div class="stat-label">平均用时</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 引入脚本 -->
|
||
<script src="../js/jquery-3.7.1.min.js"></script>
|
||
<script src="../js/apiService.js"></script>
|
||
<script src="../js/dataManager.js"></script>
|
||
<script src="../js/userManager.js"></script>
|
||
<script src="../js/aiGameGenerator.js"></script>
|
||
|
||
<script>
|
||
let currentGame = null;
|
||
let isGenerating = false;
|
||
|
||
// 页面加载完成后初始化
|
||
document.addEventListener("DOMContentLoaded", async function () {
|
||
try {
|
||
// 初始化用户管理器
|
||
await window.userManager.init();
|
||
window.userManager.createUserDisplay();
|
||
|
||
// 初始化数据管理器
|
||
await window.dataManager.init();
|
||
|
||
// 初始化AI游戏生成器
|
||
await window.aiGameGenerator.init();
|
||
|
||
// 更新统计信息
|
||
updateStats();
|
||
|
||
// 设置难度滑块事件
|
||
document
|
||
.getElementById("difficultySlider")
|
||
.addEventListener("input", function () {
|
||
document.getElementById("difficultyValue").textContent =
|
||
this.value;
|
||
window.aiGameGenerator.currentDifficulty = parseInt(this.value);
|
||
});
|
||
|
||
// 设置导航事件
|
||
document
|
||
.querySelectorAll(".container-header-nav > div")
|
||
.forEach((item) => {
|
||
item.addEventListener("click", function () {
|
||
const url = this.getAttribute("data-url");
|
||
if (url !== "ai_game_generator") {
|
||
window.open(`./${url}.html`);
|
||
}
|
||
});
|
||
});
|
||
|
||
console.log("AI游戏生成器页面初始化完成");
|
||
} catch (error) {
|
||
console.error("初始化失败:", error);
|
||
showError("初始化失败,请刷新页面重试");
|
||
}
|
||
});
|
||
|
||
// 生成游戏
|
||
async function generateGame() {
|
||
if (isGenerating) return;
|
||
|
||
const generateBtn = document.getElementById("generateBtn");
|
||
const gamePreview = document.getElementById("gamePreview");
|
||
|
||
try {
|
||
isGenerating = true;
|
||
generateBtn.disabled = true;
|
||
generateBtn.textContent = "🔄 生成中...";
|
||
|
||
// 显示加载状态
|
||
gamePreview.innerHTML = `
|
||
<div class="loading">
|
||
<div class="loading-spinner"></div>
|
||
<p>AI正在分析学习数据,生成个性化游戏...</p>
|
||
</div>
|
||
`;
|
||
|
||
// 获取当前用户
|
||
const currentUser = window.userManager.getCurrentUser();
|
||
if (!currentUser) {
|
||
throw new Error("请先登录");
|
||
}
|
||
|
||
// 获取配置
|
||
const subject = document.getElementById("subjectSelect").value;
|
||
const gameType = document.getElementById("gameTypeSelect").value;
|
||
const questionCount = parseInt(
|
||
document.getElementById("questionCountSelect").value
|
||
);
|
||
const difficulty = parseInt(
|
||
document.getElementById("difficultySlider").value
|
||
);
|
||
|
||
// 使用本地AI游戏生成器
|
||
if (!window.aiGameGenerator) {
|
||
throw new Error("AI游戏生成器未初始化");
|
||
}
|
||
|
||
// 设置难度
|
||
window.aiGameGenerator.currentDifficulty = difficulty;
|
||
|
||
// 生成完整游戏页面
|
||
const game = window.aiGameGenerator.generateGamePage(
|
||
subject,
|
||
gameType,
|
||
questionCount
|
||
);
|
||
|
||
if (game) {
|
||
currentGame = game;
|
||
// 显示游戏预览
|
||
displayGamePreview(currentGame);
|
||
showSuccess(
|
||
`成功生成${subject}学科的${gameType}游戏!游戏已嵌入当前页面。`
|
||
);
|
||
} else {
|
||
throw new Error("生成游戏失败");
|
||
}
|
||
} catch (error) {
|
||
console.error("生成游戏失败:", error);
|
||
showError("游戏生成失败,请重试");
|
||
gamePreview.innerHTML = `
|
||
<div class="loading">
|
||
<p>❌ 生成失败,请重试</p>
|
||
</div>
|
||
`;
|
||
} finally {
|
||
isGenerating = false;
|
||
generateBtn.disabled = false;
|
||
generateBtn.textContent = "🚀 生成个性化游戏";
|
||
}
|
||
}
|
||
|
||
// 显示游戏预览
|
||
function displayGamePreview(game) {
|
||
const gamePreview = document.getElementById("gamePreview");
|
||
|
||
let previewHTML = `
|
||
<div style="margin-bottom: 20px;">
|
||
<h3 style="color: #333; margin-bottom: 15px;">🎮 ${game.subject} - ${game.type} 游戏</h3>
|
||
<div style="display: flex; gap: 15px; margin-bottom: 15px; flex-wrap: wrap;">
|
||
<span style="background: #e3f2fd; color: #1976d2; padding: 5px 10px; border-radius: 15px; font-size: 0.9em;">
|
||
难度: ${game.difficulty}/5
|
||
</span>
|
||
<span style="background: #f3e5f5; color: #7b1fa2; padding: 5px 10px; border-radius: 15px; font-size: 0.9em;">
|
||
时间: ${game.timeLimit}秒
|
||
</span>
|
||
<span style="background: #e8f5e8; color: #388e3c; padding: 5px 10px; border-radius: 15px; font-size: 0.9em;">
|
||
提示: ${game.hints}次
|
||
</span>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
// 显示题目预览
|
||
game.questions.forEach((question, index) => {
|
||
previewHTML += `
|
||
<div class="question-item">
|
||
<div class="question-text">第${index + 1}题: ${
|
||
question.question
|
||
}</div>
|
||
<div class="question-options">
|
||
${question.options
|
||
.map(
|
||
(option) =>
|
||
`<div class="option-item">${option}</div>`
|
||
)
|
||
.join("")}
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
// 添加开始游戏按钮
|
||
previewHTML += `
|
||
<div style="text-align: center; margin-top: 20px;">
|
||
<button onclick="startGame()" style="
|
||
background: linear-gradient(135deg, #4caf50 0%, #45a049 100%);
|
||
color: white;
|
||
border: none;
|
||
padding: 12px 30px;
|
||
border-radius: 25px;
|
||
font-size: 1.1em;
|
||
font-weight: bold;
|
||
cursor: pointer;
|
||
transition: transform 0.2s;
|
||
" onmouseover="this.style.transform='translateY(-2px)'" onmouseout="this.style.transform='translateY(0)'">
|
||
🎯 开始游戏
|
||
</button>
|
||
</div>
|
||
`;
|
||
|
||
gamePreview.innerHTML = previewHTML;
|
||
}
|
||
|
||
// 开始游戏
|
||
function startGame() {
|
||
if (!currentGame) {
|
||
showError("请先生成游戏");
|
||
return;
|
||
}
|
||
|
||
// 这里可以跳转到游戏页面或打开游戏窗口
|
||
showSuccess("游戏即将开始!");
|
||
console.log("开始游戏:", currentGame);
|
||
|
||
// 可以在这里集成到现有的游戏系统
|
||
// 例如:window.open(`./play/game.html?gameId=${currentGame.id}`);
|
||
}
|
||
|
||
// 更新统计信息
|
||
async function updateStats() {
|
||
try {
|
||
const currentUser = window.userManager.getCurrentUser();
|
||
if (!currentUser) {
|
||
// 使用默认统计
|
||
document.getElementById("currentDifficulty").textContent = "1";
|
||
document.getElementById("totalGames").textContent = "0";
|
||
document.getElementById("successRate").textContent = "0%";
|
||
document.getElementById("avgTime").textContent = "0s";
|
||
return;
|
||
}
|
||
|
||
// 调用后端API获取统计
|
||
const response = await window.apiService.getStudentGameStats(
|
||
currentUser.id
|
||
);
|
||
|
||
if (response.success) {
|
||
const stats = response.data;
|
||
document.getElementById("currentDifficulty").textContent =
|
||
stats.currentLevel || 1;
|
||
document.getElementById("totalGames").textContent =
|
||
stats.totalGames || 0;
|
||
document.getElementById("successRate").textContent =
|
||
Math.round((stats.successRate || 0) * 100) + "%";
|
||
document.getElementById("avgTime").textContent =
|
||
Math.round(stats.avgTime || 0) + "s";
|
||
} else {
|
||
// 使用本地统计
|
||
const localStats = window.aiGameGenerator.getGameStats();
|
||
document.getElementById("currentDifficulty").textContent =
|
||
localStats.currentDifficulty;
|
||
document.getElementById("totalGames").textContent =
|
||
localStats.totalGames;
|
||
document.getElementById("successRate").textContent =
|
||
localStats.averageSuccessRate
|
||
? Math.round(localStats.averageSuccessRate * 100) + "%"
|
||
: "0%";
|
||
|
||
const avgTime =
|
||
localStats.performanceHistory.length > 0
|
||
? Math.round(
|
||
localStats.performanceHistory.reduce(
|
||
(sum, p) => sum + p.avgTimePerQuestion,
|
||
0
|
||
) / localStats.performanceHistory.length
|
||
)
|
||
: 0;
|
||
document.getElementById("avgTime").textContent = avgTime + "s";
|
||
}
|
||
} catch (error) {
|
||
console.error("获取统计信息失败:", error);
|
||
// 使用默认值
|
||
document.getElementById("currentDifficulty").textContent = "1";
|
||
document.getElementById("totalGames").textContent = "0";
|
||
document.getElementById("successRate").textContent = "0%";
|
||
document.getElementById("avgTime").textContent = "0s";
|
||
}
|
||
}
|
||
|
||
// 显示成功消息
|
||
function showSuccess(message) {
|
||
const gamePreview = document.getElementById("gamePreview");
|
||
const successDiv = document.createElement("div");
|
||
successDiv.className = "success-message";
|
||
successDiv.textContent = message;
|
||
gamePreview.insertBefore(successDiv, gamePreview.firstChild);
|
||
|
||
setTimeout(() => {
|
||
successDiv.remove();
|
||
}, 3000);
|
||
}
|
||
|
||
// 显示错误消息
|
||
function showError(message) {
|
||
const gamePreview = document.getElementById("gamePreview");
|
||
const errorDiv = document.createElement("div");
|
||
errorDiv.className = "error-message";
|
||
errorDiv.textContent = message;
|
||
gamePreview.insertBefore(errorDiv, gamePreview.firstChild);
|
||
|
||
setTimeout(() => {
|
||
errorDiv.remove();
|
||
}, 5000);
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|