视译后练习 · 热词闯关 | 口译多元挑战
by RocketGecko40733 lines34.0 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>视译后练习 · 热词闯关 | 口译多元挑战</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #fef7e8;
background-image: radial-gradient(circle at 10% 20%, rgba(255, 235, 200, 0.6) 2%, transparent 2.5%);
background-size: 28px 28px;
font-family: 'Segoe UI', 'Poppins', 'Inter', system-ui, -apple-system, 'Microsoft YaHei', sans-serif;
padding: 32px 24px;
color: #2c2418;
}
/* 主容器 */
.main-quiz-container {
max-width: 1300px;
margin: 0 auto;
}
/* 头部 */
.hero {
text-align: center;
margin-bottom: 32px;
}
.hero h1 {
font-size: 2.4rem;
background: linear-gradient(135deg, #E67E22, #F4A261);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
letter-spacing: -0.5px;
}
.hero p {
color: #b97f44;
font-weight: 500;
margin-top: 8px;
font-size: 1.05rem;
}
.score-bar {
display: flex;
justify-content: flex-end;
align-items: baseline;
gap: 28px;
background: #ffffffcc;
backdrop-filter: blur(4px);
padding: 12px 28px;
border-radius: 80px;
margin-bottom: 32px;
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
}
.score-card {
background: #fae6cf;
padding: 6px 20px;
border-radius: 40px;
font-weight: bold;
}
.score-label {
font-size: 0.8rem;
color: #a7582c;
}
.score-value {
font-size: 1.8rem;
font-weight: 800;
color: #e67e22;
line-height: 1;
}
/* 关卡选项卡 */
.level-tabs {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-bottom: 28px;
justify-content: center;
}
.level-tab {
background: #f5e6d3;
padding: 12px 26px;
border-radius: 60px;
font-weight: 600;
cursor: pointer;
transition: 0.2s;
border: 1px solid #eed7bb;
color: #7a4d2a;
}
.level-tab.active {
background: #e67e22;
color: white;
border-color: #e67e22;
box-shadow: 0 6px 12px rgba(230,126,34,0.25);
}
.level-tab.completed-tab {
background: #b7d968;
color: #2c5a1e;
border-color: #9bc45a;
}
.level-tab.locked-tab {
opacity: 0.55;
cursor: not-allowed;
background: #ddd0be;
}
/* 主体卡片: 每个关卡独立内容 */
.quiz-panel {
background: #fffef7;
border-radius: 64px;
box-shadow: 0 20px 35px rgba(100, 60, 10, 0.1);
padding: 32px 36px;
transition: 0.2s;
border: 1px solid #ffdfb8;
}
.section-title {
font-size: 1.5rem;
font-weight: 700;
border-left: 8px solid #f4a261;
padding-left: 20px;
margin-bottom: 28px;
color: #6b3f1c;
}
/* 判断题/选择题共用样式 */
.question-card {
background: #fef5ea;
border-radius: 40px;
padding: 20px 28px;
margin-bottom: 24px;
transition: all 0.1s;
border: 1px solid #ffe0bc;
}
.question-text {
font-weight: 600;
font-size: 1.05rem;
margin-bottom: 16px;
}
.options {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin: 12px 0 8px;
}
.opt-btn {
background: #ffffff;
border: 1.5px solid #f0cfaa;
padding: 8px 24px;
border-radius: 60px;
cursor: pointer;
transition: 0.1s;
font-weight: 500;
}
.opt-btn.selected {
background: #e67e22;
border-color: #e67e22;
color: white;
}
.feedback {
margin-top: 12px;
font-size: 0.85rem;
padding: 6px 12px;
border-radius: 28px;
display: inline-block;
}
.correct-fb {
background: #dcfce7;
color: #15803d;
}
.wrong-fb {
background: #ffe4e2;
color: #b91c1c;
}
/* 连线题区域 */
.match-area {
display: flex;
flex-wrap: wrap;
gap: 30px;
justify-content: space-between;
margin: 25px 0;
}
.match-col {
flex: 1;
background: #faf0e2;
border-radius: 48px;
padding: 18px;
}
.match-item {
background: white;
margin: 12px 0;
padding: 12px 16px;
border-radius: 60px;
text-align: center;
cursor: pointer;
transition: 0.08s linear;
border: 1px solid #e9cfa7;
font-weight: 500;
}
.match-item.selected-match {
background: #e67e22;
color: white;
border-color: #e67e22;
}
.paired-info {
font-size: 0.8rem;
margin-top: 16px;
text-align: center;
background: #e7dcc8;
padding: 8px;
border-radius: 40px;
}
/* 视译专区 */
.sight-card {
background: #fef2e2;
border-radius: 40px;
padding: 20px;
margin-bottom: 28px;
}
.eng-sentence {
background: #2c3e2f10;
padding: 14px;
font-family: 'Courier New', monospace;
border-left: 6px solid #f4a261;
margin-bottom: 12px;
}
textarea {
width: 100%;
background: white;
border: 1px solid #f3cfaa;
border-radius: 36px;
padding: 14px 20px;
font-size: 0.9rem;
font-family: inherit;
resize: vertical;
}
.submit-area {
text-align: right;
margin-top: 28px;
}
.submit-btn {
background: #e67e22;
border: none;
padding: 12px 32px;
border-radius: 60px;
font-weight: bold;
color: white;
font-size: 1rem;
cursor: pointer;
transition: 0.1s;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
.reset-btn {
background: #b0aa8c;
margin-right: 16px;
}
.complete-badge {
text-align: center;
background: #cbe6b0;
border-radius: 48px;
padding: 14px;
margin-top: 20px;
font-weight: bold;
}
@media (max-width: 700px) {
.quiz-panel { padding: 20px; }
.match-area { flex-direction: column; }
}
footer {
text-align: center;
margin-top: 32px;
opacity: 0.7;
}
</style>
</head>
<body>
<div class="main-quiz-container">
<div class="hero">
<h1>🎤 视译后·热词大闯关</h1>
<p>判断题 ✓ | 选择题 ✨ | 连线题 🔗 | 视译挑战 🎙️</p>
</div>
<div class="score-bar">
<div class="score-card"><span class="score-label">🏆 累计得分</span><div class="score-value" id="totalScoreDisplay">0</div></div>
<div class="score-card"><span class="score-label">📌 通关进度</span><div class="score-value" id="progressDisplay">0</div><span style="font-size:0.8rem;">/4</span></div>
</div>
<!-- 关卡选项卡 -->
<div class="level-tabs" id="levelTabs"></div>
<!-- 动态内容面板 -->
<div id="quizPanel" class="quiz-panel"></div>
<footer>🎯 每关独立计分,全部完成解锁大师成就!</footer>
</div>
<script>
// --------------------------------------------------------------
// 基于提供的四个热词构建丰富题库 (判断+选择+连线+视译)
// --------------------------------------------------------------
const levels = [
{ // 热词01 习近平会见郑丽文
id: 0,
name: "🏛️ 01 两岸会晤 · 习近平见郑丽文",
completed: false,
scoreEarned: 0,
unlocked: true,
tasks: {
truefalse: [
{ text: "习近平指出,国共两党领导人时隔10年再次会面,对两岸关系发展无足轻重。", isTrue: false, explanation: "原文明确表示“具有重要意义”,对两党关系和两岸关系发展都很重要。" },
{ text: "习近平强调,中华民族伟大复兴的大趋势不会因为国际形势变化而改变。", isTrue: true, explanation: "无论国际形势和台海局势如何演变,民族复兴的大趋势不会改变。" }
],
multipleChoice: [
{ question: "根据报道,郑丽文此访大陆有何特殊意义?", options: ["首次率团访问江苏", "时隔10年国民党主席再次率团访问大陆", "与习近平总书记签署经济协议", "宣布两岸直航新政策"], correct: 1, explanation: "郑丽文是近十年来首位率团来访大陆的国民党主席。" },
{ question: "习近平提到国共两党不可推卸的责任是什么?", options: ["实现两岸军事同盟", "推动台湾独立", "回应两岸同胞对和平与美好生活的期盼", "联合举办奥运会"], correct: 2, explanation: "两岸同胞期盼和平安宁与更好生活,这是不可推卸的责任。" }
],
matching: {
left: ["overarching trend", "national rejuvenation", "shirk responsibility"],
right: ["首要趋势", "民族复兴", "推卸责任"]
},
sightTranslation: [
{ eng: "No matter how the international landscape may evolve, the overarching trend toward the great rejuvenation of the Chinese nation will not change.", refZh: "无论国际形势如何演变,中华民族伟大复兴的大趋势不会改变。" },
{ eng: "This is a responsibility that the CPC and the KMT cannot shirk, and also a driving force for the two parties to work together.", refZh: "这是国共两党不可推卸的责任,也是携手合作的动力。" }
]
}
},
{ // 热词02 哪吒2
id: 1,
name: "🎬 02 哪吒2 · 票房传奇",
completed: false,
scoreEarned: 0,
unlocked: false,
tasks: {
truefalse: [
{ text: "《哪吒2》全球票房超越了《泰坦尼克号》,成为影史票房第三的电影。", isTrue: false, explanation: "它成为第四高票房电影,并非第三。" },
{ text: "截至4月8日,《哪吒2》全球累计票房达到22.67亿美元。", isTrue: true, explanation: "新闻原文明确提到22.67亿美元。" }
],
multipleChoice: [
{ question: "《哪吒2》的票房成绩在影史排名第几?", options: ["第二", "第三", "第四", "第五"], correct: 2, explanation: "猫眼数据显示,已升至全球第四。" },
{ question: "“blockbuster”在电影语境中最合适的含义是?", options: ["票房惨败", "大片/非常成功的电影", "小众艺术片", "动画短片"], correct: 1, explanation: "blockbuster指一鸣惊人的大片。" }
],
matching: {
left: ["box office haul", "overtake", "epic"],
right: ["票房总收入", "超越", "史诗巨制"]
},
sightTranslation: [
{ eng: "Chinese animated blockbuster 'Ne Zha 2' has overtaken 'Titanic' to become the fourth-highest-grossing film in global box office history.", refZh: "中国动画大片《哪吒2》已超越《泰坦尼克号》,成为全球影史票房第四的电影。" },
{ eng: "The film's worldwide box office haul reached 2.267 billion dollars, lifting it past James Cameron's 1997 epic.", refZh: "该片全球票房达到22.67亿美元,超越了詹姆斯·卡梅隆1997年的史诗巨制。" }
]
}
},
{ // 热词03 全红婵遭网暴
id: 2,
name: "🤺 03 全红婵 · 向网暴说不",
completed: false,
scoreEarned: 0,
unlocked: false,
tasks: {
truefalse: [
{ text: "国家体育总局游泳中心对全红婵遭遇网暴事件保持沉默,未作回应。", isTrue: false, explanation: "体育部门发布了联合声明,谴责网络暴力并报警。" },
{ text: "网暴言论可能源于一个200多人的微信群,群公告针对全红婵有攻击性内容。", isTrue: true, explanation: "媒体报道群公告明确写‘禁止攻击其他运动员(全红婵除外)’。" }
],
multipleChoice: [
{ question: "体育部门针对全红婵事件采取的措施不包括以下哪一项?", options: ["开展核查处置工作", "向警方报案", "加强运动员权益保障", "永久关闭所有粉丝群"], correct: 3, explanation: "声明提及核查、报案及抵制畸形饭圈,并未一刀切关闭所有群。" },
{ question: "以下哪个词汇最符合‘derogatory nicknames’的意思?", options: ["亲切昵称", "侮辱性外号", "官方头衔", "匿名账号"], correct: 1, explanation: "derogatory意为贬低的,侮辱性的。" }
],
matching: {
left: ["cyberbully", "toxic fan culture", "medalist"],
right: ["网络暴力", "畸形饭圈文化", "奖牌获得者"]
},
sightTranslation: [
{ eng: "Chinese sports authorities condemned online abuse after three-time Olympic gold medalist Quan Hongchan was targeted by cyberbullying.", refZh: "在三金得主全红婵遭受网暴后,中国体育部门谴责了网络暴力行为。" },
{ eng: "According to reports, the abuse may have originated from a WeChat group of over 200 members.", refZh: "据报道,这些攻击可能源于一个200多人的微信群。" }
]
}
},
{ // 热词04 陈丽华去世
id: 3,
name: "🌺 04 陈丽华 · 紫檀传奇",
completed: false,
scoreEarned: 0,
unlocked: false,
tasks: {
truefalse: [
{ text: "陈丽华曾是中国女首富,2016年财富总额达505亿元人民币。", isTrue: true, explanation: "胡润2016女富豪榜显示其财富505亿元。" },
{ text: "陈丽华曾任全国政协港澳台侨委员会主任委员。", isTrue: false, explanation: "她担任的是副主任委员。" }
],
multipleChoice: [
{ question: "陈丽华的主要荣誉身份不包括?", options: ["中国紫檀博物馆馆长", "联合国杰出亚裔女性终身成就奖", "富华国际集团名誉主席", "中国美术家协会主席"], correct: 3, explanation: "她是企业家、博物馆馆长,并非美协主席。" },
{ question: "讣告中‘liaison’在‘Committee on Liaison with Hong Kong, Macao, Taiwan and Overseas Chinese’的含义是?", options: ["联络", "私通", "隔离", "行政"], correct: 0, explanation: "这里指联络委员会。" }
],
matching: {
left: ["obituary", "sandalwood", "net worth"],
right: ["讣告", "檀香木/紫檀", "净资产"]
},
sightTranslation: [
{ eng: "Chen Lihua, Honorary Chairman of Fu Wah International Enterprises Group and Director of the China Red Sandalwood Museum, passed away at the age of 85.", refZh: "富华国际集团名誉主席、中国紫檀博物馆馆长陈丽华逝世,享年85岁。" },
{ eng: "Having served as a CPPCC member for five consecutive terms, she was also vice chairperson of several committees.", refZh: "她曾连任五届全国政协委员,并担任多个委员会副主任。" }
]
}
}
];
// 全局状态
let currentLevelId = 0; // 当前打开关卡索引
let totalScore = 0;
let levelAnswers = {}; // 存储每个关卡的选择/判断/连线/视译临时答案
// 连线配对状态存储 (每个关卡独立)
let matchPairsState = {}; // { levelId: { pairs: [{leftIdx, rightIdx}], leftSelected, rightSelected } }
// DOM 元素
const levelTabsDiv = document.getElementById('levelTabs');
const quizPanel = document.getElementById('quizPanel');
const totalScoreSpan = document.getElementById('totalScoreDisplay');
const progressSpan = document.getElementById('progressDisplay');
function saveGlobalScore() {
totalScore = levels.reduce((sum, lvl) => sum + (lvl.completed ? lvl.scoreEarned : 0), 0);
totalScoreSpan.innerText = totalScore;
const completedCount = levels.filter(l => l.completed).length;
progressSpan.innerText = completedCount;
// 解锁逻辑:完成前一关自动解锁下一个未解锁关卡
for (let i = 0; i < levels.length; i++) {
if (i === 0) levels[i].unlocked = true;
else if (levels[i-1].completed && !levels[i].unlocked) {
levels[i].unlocked = true;
}
}
renderTabs();
}
function renderTabs() {
levelTabsDiv.innerHTML = '';
levels.forEach((level, idx) => {
const tab = document.createElement('div');
tab.className = `level-tab ${currentLevelId === idx ? 'active' : ''} ${level.completed ? 'completed-tab' : ''} ${!level.unlocked ? 'locked-tab' : ''}`;
tab.innerText = `${level.name} ${level.completed ? '✓' : ''}`;
if (level.unlocked) {
tab.addEventListener('click', () => {
if (level.unlocked) {
currentLevelId = idx;
renderCurrentLevel();
renderTabs();
}
});
} else {
tab.style.cursor = 'not-allowed';
}
levelTabsDiv.appendChild(tab);
});
}
// 初始化某关卡的连线配对存储
function initMatchStorage(levelId, leftLen, rightLen) {
if (!matchPairsState[levelId]) {
matchPairsState[levelId] = {
pairs: [], // 存储配对 {leftIdx, rightIdx}
leftSelected: null,
rightSelected: null
};
}
}
// 渲染当前关卡所有题型
function renderCurrentLevel() {
const level = levels[currentLevelId];
if (!level) return;
const tasks = level.tasks;
// 构建html
let html = `<div class="section-title">📖 ${level.name} · 题型闯关</div>`;
// 1. 判断题区域
html += `<div style="margin-bottom: 30px;"><h3>⚖️ 判断题 (每题5分)</h3>`;
tasks.truefalse.forEach((item, idx) => {
const saved = levelAnswers[`tf_${currentLevelId}_${idx}`];
html += `
<div class="question-card">
<div class="question-text">${idx+1}. ${item.text}</div>
<div class="options">
<div class="opt-btn" data-type="tf" data-qidx="${idx}" data-val="true">✅ 正确</div>
<div class="opt-btn" data-type="tf" data-qidx="${idx}" data-val="false">❌ 错误</div>
</div>
<div id="tf_fb_${idx}" class="feedback"></div>
</div>
`;
});
html += `</div>`;
// 2. 选择题区域
html += `<div style="margin-bottom: 30px;"><h3>🔍 选择题 (每题8分)</h3>`;
tasks.multipleChoice.forEach((mc, idx) => {
const saved = levelAnswers[`mc_${currentLevelId}_${idx}`];
html += `<div class="question-card">
<div class="question-text">${idx+1}. ${mc.question}</div>
<div class="options">`;
mc.options.forEach((opt, optIdx) => {
html += `<div class="opt-btn" data-type="mc" data-qidx="${idx}" data-opt="${optIdx}">${String.fromCharCode(65+optIdx)}. ${opt}</div>`;
});
html += `</div><div id="mc_fb_${idx}" class="feedback"></div></div>`;
});
html += `</div>`;
// 3. 连线题区域
const match = tasks.matching;
const leftItems = match.left;
const rightItems = match.right;
initMatchStorage(currentLevelId, leftItems.length, rightItems.length);
const storage = matchPairsState[currentLevelId];
// 计算已配对数量用于展示
const pairedCount = storage.pairs.length;
html += `<div style="margin-bottom: 30px;"><h3>🔗 连线匹配 (每正确配对一组6分,满分18分)</h3>
<div class="match-area">
<div class="match-col"><strong>左列(术语)</strong><div id="matchLeftCol">${leftItems.map((l, i) => `<div class="match-item" data-side="left" data-idx="${i}">${l}</div>`).join('')}</div></div>
<div class="match-col"><strong>右列(释义)</strong><div id="matchRightCol">${rightItems.map((r, i) => `<div class="match-item" data-side="right" data-idx="${i}">${r}</div>`).join('')}</div></div>
</div>
<div id="matchStatusMsg" class="paired-info">✔️ 当前配对: ${pairedCount} / ${leftItems.length} 组</div>
<div id="matchFeedbackMsg" style="font-size:0.8rem; margin-top:6px;"></div>
</div>`;
// 4. 视译题
html += `<div><h3>🎙️ 视译题 (每句满分12分)</h3>`;
tasks.sightTranslation.forEach((item, idx) => {
const savedText = levelAnswers[`sight_${currentLevelId}_${idx}`] || '';
html += `<div class="sight-card">
<div class="eng-sentence">📖 ${item.eng}</div>
<textarea rows="2" class="sight-textarea" data-sightidx="${idx}" placeholder="输入中文视译...">${savedText}</textarea>
<div id="sight_fb_${idx}" class="feedback"></div>
<div style="font-size:0.7rem; opacity:0.6;">参考译文: ${item.refZh.substring(0,70)}…</div>
</div>`;
});
html += `</div>`;
html += `<div class="submit-area">
<button class="reset-btn" id="resetLevelBtn">🔄 重置本关答案</button>
<button class="submit-btn" id="submitLevelBtn">✨ 提交本关 · 获得分数 ✨</button>
</div>`;
if (level.completed) {
html += `<div class="complete-badge">🏅 本关已通关! 得分: ${level.scoreEarned} 分。可再次练习但分数不重复累计。</div>`;
}
quizPanel.innerHTML = html;
// 绑定事件:判断/选择题高亮及暂存
document.querySelectorAll('.opt-btn[data-type="tf"]').forEach(btn => {
btn.addEventListener('click', (e) => {
const qidx = parseInt(btn.dataset.qidx);
const val = btn.dataset.val === 'true';
const parentDiv = btn.closest('.question-card');
parentDiv.querySelectorAll('.opt-btn').forEach(b => b.classList.remove('selected'));
btn.classList.add('selected');
levelAnswers[`tf_${currentLevelId}_${qidx}`] = val;
// 清除旧反馈
document.getElementById(`tf_fb_${qidx}`).innerHTML = '';
});
});
document.querySelectorAll('.opt-btn[data-type="mc"]').forEach(btn => {
btn.addEventListener('click', (e) => {
const qidx = parseInt(btn.dataset.qidx);
const opt = parseInt(btn.dataset.opt);
const parentDiv = btn.closest('.question-card');
parentDiv.querySelectorAll('.opt-btn').forEach(b => b.classList.remove('selected'));
btn.classList.add('selected');
levelAnswers[`mc_${currentLevelId}_${qidx}`] = opt;
document.getElementById(`mc_fb_${qidx}`).innerHTML = '';
});
});
// 连线逻辑重新挂载
attachMatchEvents(currentLevelId, leftItems, rightItems);
// 视译输入暂存
document.querySelectorAll('.sight-textarea').forEach(ta => {
const idx = parseInt(ta.dataset.sightidx);
ta.addEventListener('input', (e) => {
levelAnswers[`sight_${currentLevelId}_${idx}`] = ta.value;
});
});
// 重置按钮
document.getElementById('resetLevelBtn')?.addEventListener('click', () => resetCurrentLevel());
// 提交得分按钮
document.getElementById('submitLevelBtn')?.addEventListener('click', () => evaluateAndSubmit());
}
function attachMatchEvents(levelId, leftArr, rightArr) {
const storage = matchPairsState[levelId];
if (!storage) return;
const leftItemsDom = document.querySelectorAll('.match-item[data-side="left"]');
const rightItemsDom = document.querySelectorAll('.match-item[data-side="right"]');
const updateHighlight = () => {
leftItemsDom.forEach(l => l.classList.remove('selected-match'));
rightItemsDom.forEach(r => r.classList.remove('selected-match'));
if(storage.leftSelected !== null) {
const target = document.querySelector(`.match-item[data-side="left"][data-idx="${storage.leftSelected}"]`);
if(target) target.classList.add('selected-match');
}
if(storage.rightSelected !== null) {
const target = document.querySelector(`.match-item[data-side="right"][data-idx="${storage.rightSelected}"]`);
if(target) target.classList.add('selected-match');
}
};
const makePair = (leftIdx, rightIdx) => {
const leftWord = leftArr[leftIdx];
const rightWord = rightArr[rightIdx];
// 验证配对是否正确 (依据热词内容)
const expectedPairs = [
{l:"overarching trend", r:"首要趋势"},{l:"national rejuvenation", r:"民族复兴"},{l:"shirk responsibility", r:"推卸责任"},
{l:"box office haul", r:"票房总收入"},{l:"overtake", r:"超越"},{l:"epic", r:"史诗巨制"},
{l:"cyberbully", r:"网络暴力"},{l:"toxic fan culture", r:"畸形饭圈文化"},{l:"medalist", r:"奖牌获得者"},
{l:"obituary", r:"讣告"},{l:"sandalwood", r:"檀香木/紫檀"},{l:"net worth", r:"净资产"}
];
let isValid = expectedPairs.some(p => (p.l === leftWord && p.r === rightWord));
if(isValid && !storage.pairs.some(p => p.left === leftIdx && p.right === rightIdx)) {
storage.pairs.push({left: leftIdx, right: rightIdx});
document.getElementById('matchStatusMsg').innerHTML = `✔️ 当前配对: ${storage.pairs.length} / ${leftArr.length} 组`;
document.getElementById('matchFeedbackMsg').innerHTML = '✅ 配对成功!';
setTimeout(()=>{if(document.getElementById('matchFeedbackMsg')) document.getElementById('matchFeedbackMsg').innerHTML = '';}, 1000);
} else if(!isValid){
document.getElementById('matchFeedbackMsg').innerHTML = '❌ 配对错误,请匹配正确术语';
setTimeout(()=>{if(document.getElementById('matchFeedbackMsg')) document.getElementById('matchFeedbackMsg').innerHTML = '';}, 1000);
}
storage.leftSelected = null;
storage.rightSelected = null;
updateHighlight();
};
const onLeftClick = (e) => {
const leftIdx = parseInt(e.currentTarget.dataset.idx);
if(storage.rightSelected !== null) {
makePair(leftIdx, storage.rightSelected);
storage.rightSelected = null;
} else {
storage.leftSelected = leftIdx;
storage.rightSelected = null;
updateHighlight();
}
};
const onRightClick = (e) => {
const rightIdx = parseInt(e.currentTarget.dataset.idx);
if(storage.leftSelected !== null) {
makePair(storage.leftSelected, rightIdx);
storage.leftSelected = null;
} else {
storage.rightSelected = rightIdx;
storage.leftSelected = null;
updateHighlight();
}
};
leftItemsDom.forEach(el => { el.removeEventListener('click', onLeftClick); el.addEventListener('click', onLeftClick); });
rightItemsDom.forEach(el => { el.removeEventListener('click', onRightClick); el.addEventListener('click', onRightClick); });
updateHighlight();
}
function resetCurrentLevel() {
const level = levels[currentLevelId];
if(level.completed) { alert("本关已通关,重置不会清除已获分数,但会清空答题记录。"); }
// 清空存储的临时答案
for(let key in levelAnswers) {
if(key.includes(`_${currentLevelId}_`)) delete levelAnswers[key];
}
if(matchPairsState[currentLevelId]) matchPairsState[currentLevelId] = { pairs: [], leftSelected: null, rightSelected: null };
renderCurrentLevel();
}
function evaluateAndSubmit() {
const level = levels[currentLevelId];
if(level.completed) {
alert(`本关已通关,得分 ${level.scoreEarned}。再次练习不重复计分。`);
return;
}
let score = 0;
const tasks = level.tasks;
// 判断评分
tasks.truefalse.forEach((item, idx) => {
const user = levelAnswers[`tf_${currentLevelId}_${idx}`];
const isCor = (user === item.isTrue);
const fbDiv = document.getElementById(`tf_fb_${idx}`);
if(isCor) { score += 5; if(fbDiv) fbDiv.innerHTML = '✓ 正确 +5分'; fbDiv.className = 'feedback correct-fb';}
else { if(fbDiv) fbDiv.innerHTML = `✗ 错误。正确答案: ${item.isTrue ? '正确' : '错误'}。 ${item.explanation}`; fbDiv.className = 'feedback wrong-fb';}
});
// 选择题
tasks.multipleChoice.forEach((mc, idx) => {
const userOpt = levelAnswers[`mc_${currentLevelId}_${idx}`];
const correct = (userOpt === mc.correct);
const fbDiv = document.getElementById(`mc_fb_${idx}`);
if(correct) { score += 8; if(fbDiv) fbDiv.innerHTML = '✓ 正确 +8分'; fbDiv.className = 'feedback correct-fb';}
else { if(fbDiv) fbDiv.innerHTML = `✗ 错误。正确答案: ${mc.options[mc.correct]}。${mc.explanation}`; fbDiv.className = 'feedback wrong-fb';}
});
// 连线评分 每组6分 上限18
const matchStore = matchPairsState[currentLevelId];
let matchPoints = 0;
if(matchStore && matchStore.pairs) {
matchPoints = Math.min(18, matchStore.pairs.length * 6);
score += matchPoints;
document.getElementById('matchStatusMsg').innerHTML += ` · 获得连线分 ${matchPoints}/18`;
}
// 视译评分 (每题12分, 酌情给分)
let sightScore = 0;
tasks.sightTranslation.forEach((item, idx) => {
const userTrans = levelAnswers[`sight_${currentLevelId}_${idx}`] || '';
let pts = 0;
if(userTrans.trim().length >= 6) pts = 8;
if(userTrans.includes(item.refZh.substring(2,12)) || userTrans.length > 15) pts = 12;
if(userTrans.trim() === item.refZh) pts = 12;
else if(userTrans.length>0 && pts===0) pts=4;
sightScore += pts;
const fbSpan = document.getElementById(`sight_fb_${idx}`);
if(fbSpan) fbSpan.innerHTML = `视译得分: ${pts}/12 (参考: ${item.refZh.substring(0,45)}…)`;
});
score += sightScore;
score = Math.min(100, score);
// 通关记录
level.completed = true;
level.scoreEarned = score;
saveGlobalScore();
renderCurrentLevel(); // 刷新显示通关标志
alert(`🏆 恭喜通关「${level.name}」\n获得 ${score}/100 分!总积分已达 ${totalScore+score} 分`);
renderTabs();
}
// 初始化渲染
function init() {
saveGlobalScore();
renderTabs();
renderCurrentLevel();
}
init();
</script>
</body>
</html>Game Source: 视译后练习 · 热词闯关 | 口译多元挑战
Creator: RocketGecko40
Libraries: none
Complexity: complex (733 lines, 34.0 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-rocketgecko40" to link back to the original. Then publish at arcadelab.ai/publish.