File: /var/www/html/simulink/xp/G9_HV_Stucture.php
<?php
require_once('../../../wp-load.php');
$user = wp_get_current_user();
global $wpdb;
$student = $user->ID ? $wpdb->get_row("SELECT * FROM {$wpdb->prefix}edu_students WHERE user_id = $user->ID") : null;
?>
<div>
<?php if ($user->ID && $student) { ?>
<div style="float:right;">学号: <?php echo esc_html($student->student_id); ?> 姓名: <?php echo esc_html($student->name); ?></div>
<?php } else { ?>
<p>未登录用户无法统计成绩,但可答题。<a href="<?php echo wp_login_url(); ?>">登录</a></p>
<?php } ?>
</div>
<!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>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f0f2f5;
display: flex;
justify-content: center;
align-items: flex-start;
min-height: 100vh;
margin: 0;
padding: 20px;
box-sizing: border-box;
}
.game-container {
background-color: #ffffff;
padding: 25px;
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
width: 95%;
max-width: 950px;
text-align: center;
}
h1 {
color: #333;
margin-bottom: 20px;
}
.info-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
background-color: #e9ecef;
border-radius: 8px;
margin-bottom: 20px;
font-size: 1.2em;
}
.timer-container { color: #1a73e8; font-weight: bold; }
#timer { display: inline-block; min-width: 50px; }
.results-container { color: #555; font-weight: 500; }
#diagram-wrapper {
position: relative;
width: 100%;
margin: 0 auto;
background-color: black;
}
.diagram-svg {
width: 100%;
height: auto;
display: block;
}
/* SVG 元素样式 */
.axle-bg { fill: #ffffff; }
.wheel { fill: #4a4a4a; }
.axle { fill: #b0b0b0; }
.component-box {
fill: #fbe5d6; /* 浅橙色背景 */
stroke: #b1a091;
stroke-width: 1;
}
.battery { fill: #fbe5d6; }
.motor-symbol {
fill: none;
stroke: #888;
stroke-width: 2;
}
.component-label {
font-size: 12px;
text-anchor: middle;
fill: #333;
font-family: sans-serif;
}
.wiring .wire {
fill: none;
stroke: #ed7d31; /* 橙色线 */
stroke-width: 3;
stroke-linecap: round;
stroke-linejoin: round;
}
.drop-zone {
position: absolute;
border: 2px dashed #aaa;
background-color: rgba(255, 255, 255, 0.6);
display: flex;
justify-content: center;
align-items: center;
font-size: 1.8vw;
font-weight: bold;
color: #333;
transition: background-color 0.3s, border-color 0.3s;
overflow: hidden;
box-sizing: border-box;
z-index: 10;
}
/* === 针对SVG的精准定位 (基于百分比) top: 方框上边缘距离整个图区(黑色背景)顶部的百分比。值越小,越靠上。=== */
/* === left: 方框左边缘距离整个图区左侧的百分比。值越小,越靠左。=== */
/* === width: 方框的宽度(占整个图区宽度的百分比)。=== */
/* === height: 方框的高度(占整个图区高度的百分比)。=== */
#drop-1 { top: 47.0%; left: 18%; width: 4.4%; height: 6.7%; }
#drop-2 { top: 40.0%; left: 24.2%; width: 6.3%; height: 6.7%; }
#drop-3 { top: 45.0%; left: 10.6%; width: 6.3%; height: 10.0%; }
#drop-4 { top: 38.2%; left: 42.3%; width: 17.4%; height: 18.3%; }
#drop-5 { top: 40.0%; left: 69.5%; width: 6.3%; height: 6.7%; }
#drop-6 { top: 45.0%; left: 82.15%; width: 6.3%; height: 10.0%; }
#drop-7 { top: 56.7%; left: 92.6%; width: 6.3%; height: 6.7%; }
#drop-8 { top: 18.3%; left: 79%; width: 3.2%; height: 5.0%; }
#drop-9 { top: 18.3%; left: 84.2%; width: 3.2%; height: 5.0%; }
#drop-10 { top: 18.3%; left: 89.2%; width: 3.2%; height: 5.0%; }
.drop-zone.drag-over { background-color: rgba(144, 238, 144, 0.7); border-color: #28a745; }
.drop-zone.correct { background-color: rgba(40, 167, 69, 0.8); border: 2px solid #1a5d2a; color: white; }
.drop-zone.incorrect { background-color: rgba(220, 53, 69, 0.8); border: 2px solid #8d1c27; color: white; }
#answer-bank { margin-top: 25px; padding: 15px; background-color: #f8f9fa; border-radius: 8px; border: 1px solid #dee2e6; }
.answers { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 10px; min-height: 50px; padding: 10px; border: 2px dashed transparent; transition: background-color 0.3s, border-color 0.3s; }
.answers.drag-over { background-color: #e9ecef; border-color: #007bff; }
.draggable {
padding: 10px 15px;
background-color: #007bff;
color: white;
border-radius: 6px;
cursor: grab;
transition: transform 0.2s, box-shadow 0.2s;
user-select: none;
font-size: 0.9em;
flex-shrink: 0;
}
.draggable.dragging { opacity: 0.5; cursor: grabbing; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); transform: scale(1.05); }
.drop-zone .draggable {
width: 100%;
height: 100%;
padding: 2px;
font-size: 13px;
line-height: 1.2;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
box-sizing: border-box;
cursor: grab;
background-color: #6c757d !important;
}
.drop-zone.correct .draggable,
.drop-zone.incorrect .draggable {
cursor: default;
background-color: transparent !important;
}
#submit-btn { margin-top: 25px; padding: 12px 30px; font-size: 1.1em; font-weight: bold; color: white; background-color: #28a745; border: none; border-radius: 8px; cursor: pointer; transition: background-color 0.3s; }
#submit-btn:hover { background-color: #218838; }
#submit-btn:disabled { background-color: #6c757d; cursor: not-allowed; }
</style>
</head>
<body>
<div class="game-container">
<h1>新能源汽车三电系统 闯关游戏</h1>
<div class="info-bar">
<div class="timer-container">
用时: <span id="timer">00:00</span>
</div>
<div id="results" class="results-container">
请将答案拖拽到对应的数字上
</div>
</div>
<div id="diagram-wrapper">
<!-- 使用SVG绘制的结构图 -->
<svg viewBox="0 0 950 600" preserveAspectRatio="xMidYMid meet" class="diagram-svg">
<!-- 背景和车轴框架 -->
<rect class="axle-bg" x="0" y="0" width="180" height="600" />
<rect class="axle-bg" x="770" y="0" width="180" height="600" />
<!-- 车轮和车轴 -->
<g class="wheel-assembly">
<!-- 左侧 -->
<rect class="wheel" x="50" y="20" width="80" height="40" rx="15"/>
<rect class="axle" x="85" y="60" width="10" height="480"/>
<rect class="wheel" x="50" y="540" width="80" height="40" rx="15"/>
<!-- 右侧 -->
<rect class="wheel" x="820" y="20" width="80" height="40" rx="15"/>
<rect class="axle" x="855" y="60" width="10" height="480"/>
<rect class="wheel" x="820" y="540" width="80" height="40" rx="15"/>
</g>
<!-- 主要部件 -->
<g class="components">
<!-- 前电机/减速器 (3) -->
<rect class="component-box" id="component-3" x="100" y="270" width="60" height="60"/>
<ellipse class="motor-symbol" cx="130" cy="300" rx="20" ry="12"/>
<!-- 【新增】减速器文本框 -->
<rect class="component-box" x="65" y="227" width="100" height="43" rx="2"/>
<text class="component-label" x="112" y="252">差速器-减速器</text>
<!-- 后电机/减速器 (6) -->
<rect class="component-box" id="component-6" x="780" y="270" width="60" height="60"/>
<ellipse class="motor-symbol" cx="810" cy="300" rx="20" ry="12"/>
<!-- 【新增】减速器文本框 -->
<rect class="component-box" x="775" y="227" width="100" height="43" rx="2"/>
<text class="component-label" x="825" y="253">减速器-差速器</text>
<!-- 前电机控制器 (1) -->
<rect class="component-box" id="component-1" x="169.5" y="283" width="44" height="40"/>
<!-- 高压配电箱PDU (2) -->
<rect class="component-box" id="component-2" x="230" y="240" width="60" height="40"/>
<!-- PTC -->
<rect class="component-box" id="component-2" x="210" y="375" width="40" height="30"/>
<text class="component-label" x="230" y="395">PTC</text>
<!-- ACP -->
<rect class="component-box" id="component-2" x="260" y="375" width="90" height="30"/>
<text class="component-label" x="305" y="395">电动压缩机ACP</text>
<!-- 后电机控制器 (5) -->
<rect class="component-box" id="component-5" x="660" y="240" width="60" height="40"/>
<!-- 二合一 OBC/DCDC (7) -->
<rect class="component-box" id="component-7" x="880" y="340" width="60" height="40"/>
<!-- 动力电池 (4) -->
<rect class="component-box battery" id="component-4" x="320" y="215" width="310" height="150"/>
<!-- 充电口 (8, 9) -->
<rect class="component-box charge-port" id="component-8" x="750" y="110" width="30" height="30"/>
<rect class="component-box charge-port" id="component-9" x="800" y="110" width="30" height="30"/>
</g>
<!-- 电路连接线 -->
<!-- 路径数据 (d="...")-->
<!-- d 属性定义了路径的形状。它由一系列命令和坐标组成。我们这个图里主要用了三个命令:-->
<!-- M x y: Move To (移动到)。相当于“抬起画笔”,移动到坐标 (x, y) 作为起点。-->
<!-- H x: Horizontal Line To (画水平线到)。从当前点画一条水平线,直到X坐标为 x。-->
<!-- V y: Vertical Line To (画垂直线到)。从当前点画一条垂直线,直到Y坐标为 y。-->
<!-- 坐标系的原点(0, 0)在SVG画布的左上角。-->
<g class="wiring">
<!-- 前电机控制器(1) -> 前电机(3) -->
<path class="wire" d="M 180 290 H 160" />
<path class="wire" d="M 180 300 H 160" />
<path class="wire" d="M 180 310 H 160" />
<!-- PDU(2) -> 前电机(3) -->
<path class="wire" d="M 230 250 H 190 V 285" />
<path class="wire" d="M 230 260 H 200 V 285" />
<!-- PDU(2) -> PTC -->
<path class="wire" d="M 240 270 V 380" />
<path class="wire" d="M 245 270 V 380" />
<!-- PDU(2) -> ACP -->
<path class="wire" d="M 270 270 V 380" />
<path class="wire" d="M 275 270 V 380" />
<!-- PDU(2) -> 电池(4) -->
<path class="wire" d="M 290 265 H 620" />
<path class="wire" d="M 290 270 H 620" />
<!-- 电池(4) -> 后电机控制器(5) -->
<path class="wire" d="M 620 250 H 660" />
<path class="wire" d="M 620 255 H 660" />
<!-- 后电机控制器(5) -> 后电机(6) -->
<path class="wire" d="M 720 250 H 750 V 280 H 790" />
<path class="wire" d="M 720 255 H 745 V 285 H 790" />
<path class="wire" d="M 720 260 H 740 V 290 H 790" />
<!-- 电池 -> 后电机(6)升压线 -->
<path class="wire" d="M 620 300 H 790" />
<!-- 电池(4)->二合一(7) -->
<path class="wire" d="M 620 350 H 890" />
<path class="wire" d="M 620 355 H 890" />
<!-- 直流充电口(8) -> 电池(4) -->
<path class="wire" d="M 765 140 V 210 H 620 V 220" />
<path class="wire" d="M 760 140 V 205 H 615 V 220" />
<!-- 交流充电口(9) -> 二合一(7) -->
<path class="wire" d="M 807 140 V 210 H 905 V 350" />
<path class="wire" d="M 812 140 V 205 H 910 V 350" />
<path class="wire" d="M 817 140 V 200 H 915 V 350" />
<path class="wire" d="M 822 140 V 195 H 920 V 350" />
</g>
</svg>
<!-- 答题区 (Drop Zones) - 覆盖在SVG之上 -->
<div class="drop-zone" id="drop-1" data-answer="前电机控制器">1</div>
<div class="drop-zone" id="drop-2" data-answer="高压配电箱PDU">2</div>
<div class="drop-zone" id="drop-3" data-answer="前电机">3</div>
<div class="drop-zone" id="drop-4" data-answer="动力电池">4</div>
<div class="drop-zone" id="drop-5" data-answer="后电机控制器">5</div>
<div class="drop-zone" id="drop-6" data-answer="后电机">6</div>
<div class="drop-zone" id="drop-7" data-answer="二合一(OBC、DCDC)">7</div>
<div class="drop-zone" id="drop-8" data-answer="直流充电口">8</div>
<div class="drop-zone" id="drop-9" data-answer="交流充电口">9</div>
</div>
<div id="answer-bank">
<h3>备选答案区 (请拖拽)</h3>
<div class="answers">
<!-- 正确答案 -->
<div class="draggable" draggable="true" data-id="ans-1">前电机</div>
<div class="draggable" draggable="true" data-id="ans-2">前电机控制器</div>
<div class="draggable" draggable="true" data-id="ans-3">高压配电箱PDU</div>
<div class="draggable" draggable="true" data-id="ans-4">动力电池</div>
<div class="draggable" draggable="true" data-id="ans-5">后电机控制器</div>
<div class="draggable" draggable="true" data-id="ans-6">后电机</div>
<div class="draggable" draggable="true" data-id="ans-7">二合一(OBC、DCDC)</div>
<div class="draggable" draggable="true" data-id="ans-8">直流充电口</div>
<div class="draggable" draggable="true" data-id="ans-9">交流充电口</div>
<!-- 干扰项 -->
<div class="draggable" draggable="true" data-id="dist-1">OBC</div>
<div class="draggable" draggable="true" data-id="dist-2">DCDC</div>
<div class="draggable" draggable="true" data-id="dist-3">后PDU</div>
</div>
</div>
<button id="submit-btn">提交答案</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// --- 状态变量 ---
let timerInterval;
let seconds = 0;
let gameEnded = false;
let draggedItem = null;
// --- DOM 元素 ---
const draggables = document.querySelectorAll('.draggable');
const dropZones = document.querySelectorAll('.drop-zone');
const answerBankContainer = document.querySelector('.answers');
const submitBtn = document.getElementById('submit-btn');
const timerDisplay = document.getElementById('timer');
const resultsDisplay = document.getElementById('results');
// --- 计时器功能 ---
const startTimer = () => {
const startTime = Date.now();
timerInterval = setInterval(() => {
if (gameEnded) return;
seconds = Math.floor((Date.now() - startTime) / 1000);
const mins = Math.floor(seconds / 60).toString().padStart(2, '0');
const secs = (seconds % 60).toString().padStart(2, '0');
timerDisplay.textContent = `${mins}:${secs}`;
}, 1000);
};
const stopTimer = () => {
clearInterval(timerInterval);
};
// --- 随机化答案功能 ---
const shuffleAnswers = () => {
const answersArray = Array.from(draggables);
for (let i = answersArray.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[answersArray[i], answersArray[j]] = [answersArray[j], answersArray[i]];
}
answersArray.forEach(answer => answerBankContainer.appendChild(answer));
};
// --- 拖放事件处理 ---
function handleDragStart(e) {
if (gameEnded) return;
draggedItem = e.target;
e.dataTransfer.setData('text/plain', draggedItem.dataset.id);
setTimeout(() => draggedItem.classList.add('dragging'), 0);
}
function handleDragEnd() {
if (draggedItem) {
draggedItem.classList.remove('dragging');
}
draggedItem = null;
}
function handleDragOver(e) {
e.preventDefault();
if (gameEnded) return;
this.classList.add('drag-over');
}
function handleDragLeave(e) {
this.classList.remove('drag-over');
}
function handleDrop(e) {
e.preventDefault();
if (gameEnded || !draggedItem) return;
this.classList.remove('drag-over');
const oldParent = draggedItem.parentElement;
if (this.classList.contains('drop-zone') && this.children.length > 0) {
answerBankContainer.appendChild(this.firstElementChild);
}
this.appendChild(draggedItem);
if (oldParent.classList.contains('drop-zone') && oldParent.children.length === 0) {
oldParent.style.color = '';
}
if (this.classList.contains('drop-zone')) {
this.style.color = 'transparent';
}
}
// --- 游戏逻辑 ---
const checkAnswers = () => {
gameEnded = true;
stopTimer();
submitBtn.disabled = true;
let score = 0;
const totalQuestions = 9;
dropZones.forEach(zone => {
const answerElement = zone.querySelector('.draggable');
if (answerElement) {
const droppedAnswer = answerElement.textContent.trim();
const correctAnswer = zone.dataset.answer;
if (droppedAnswer === correctAnswer) {
zone.classList.add('correct');
score++;
} else {
zone.classList.add('incorrect');
}
} else {
zone.classList.add('incorrect');
}
});
const percentageScore = Math.round((score / totalQuestions) * 100);
const finalTime = timerDisplay.textContent;
resultsDisplay.innerHTML = `🎉 游戏结束! 得分: ${score}/${totalQuestions} (<strong>${percentageScore}分</strong>). 用时: <strong>${finalTime}</strong>`;
};
// --- 初始化 ---
draggables.forEach(draggable => {
draggable.addEventListener('dragstart', handleDragStart);
draggable.addEventListener('dragend', handleDragEnd);
});
dropZones.forEach(zone => {
zone.addEventListener('dragover', handleDragOver);
zone.addEventListener('dragleave', handleDragLeave);
zone.addEventListener('drop', handleDrop);
});
answerBankContainer.addEventListener('dragover', handleDragOver);
answerBankContainer.addEventListener('dragleave', handleDragLeave);
answerBankContainer.addEventListener('drop', handleDrop);
submitBtn.addEventListener('click', checkAnswers);
shuffleAnswers();
startTimer();
});
</script>
</body>
</html>