Refactor code structure for improved readability and maintainability
All checks were successful
Deploy / deploy (push) Successful in 2s
All checks were successful
Deploy / deploy (push) Successful in 2s
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.superpowers
|
||||||
103
app.js
103
app.js
@@ -93,7 +93,7 @@ function sfxComplete() {
|
|||||||
const APP_VERSION = 2;
|
const APP_VERSION = 2;
|
||||||
var state = {
|
var state = {
|
||||||
sound: true,
|
sound: true,
|
||||||
bigFont: false,
|
theme: "ink",
|
||||||
difficulty: 1,
|
difficulty: 1,
|
||||||
score: 0,
|
score: 0,
|
||||||
combo: 0,
|
combo: 0,
|
||||||
@@ -123,7 +123,7 @@ function saveState() {
|
|||||||
"chengyu_s",
|
"chengyu_s",
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
sound: state.sound,
|
sound: state.sound,
|
||||||
bigFont: state.bigFont,
|
theme: state.theme,
|
||||||
difficulty: state.difficulty,
|
difficulty: state.difficulty,
|
||||||
totalCount: state.totalCount,
|
totalCount: state.totalCount,
|
||||||
streak: state.streak,
|
streak: state.streak,
|
||||||
@@ -237,7 +237,7 @@ function loadState() {
|
|||||||
try {
|
try {
|
||||||
var s = JSON.parse(localStorage.getItem("chengyu_s") || "{}");
|
var s = JSON.parse(localStorage.getItem("chengyu_s") || "{}");
|
||||||
state.sound = s.sound !== undefined ? s.sound : true;
|
state.sound = s.sound !== undefined ? s.sound : true;
|
||||||
state.bigFont = s.bigFont || false;
|
state.theme = s.theme || "ink";
|
||||||
state.totalCount = s.totalCount || 0;
|
state.totalCount = s.totalCount || 0;
|
||||||
state.streak = s.streak || 0;
|
state.streak = s.streak || 0;
|
||||||
state.checkinDays = s.checkinDays || [];
|
state.checkinDays = s.checkinDays || [];
|
||||||
@@ -312,16 +312,15 @@ function pickIdiom() {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
var pool = IDIOMS.filter(function (i) {
|
var pool = IDIOMS.filter(function (i) {
|
||||||
return i.l <= state.difficulty;
|
return i.l <= state.difficulty && !state.usedIdiomIndices[i.w];
|
||||||
});
|
});
|
||||||
var a = 0,
|
if (!pool.length) {
|
||||||
idx;
|
state.usedIdiomIndices = {};
|
||||||
do {
|
pool = IDIOMS.filter(function (i) { return i.l <= state.difficulty; });
|
||||||
idx = Math.floor(Math.random() * pool.length);
|
}
|
||||||
a++;
|
var item = pool[Math.floor(Math.random() * pool.length)];
|
||||||
} while (state.usedIdiomIndices[pool[idx].w] && a < 100);
|
state.usedIdiomIndices[item.w] = 1;
|
||||||
state.usedIdiomIndices[pool[idx].w] = 1;
|
return item;
|
||||||
return pool[idx];
|
|
||||||
}
|
}
|
||||||
function generateBlanks(w, d) {
|
function generateBlanks(w, d) {
|
||||||
var n = d === 1 ? 1 : d === 2 ? 2 : 3;
|
var n = d === 1 ? 1 : d === 2 ? 2 : 3;
|
||||||
@@ -375,6 +374,11 @@ function renderStats() {
|
|||||||
document.getElementById("statCombo").textContent = state.combo;
|
document.getElementById("statCombo").textContent = state.combo;
|
||||||
document.getElementById("statTotal").textContent = state.totalCount;
|
document.getElementById("statTotal").textContent = state.totalCount;
|
||||||
document.getElementById("statStreak").textContent = state.streak;
|
document.getElementById("statStreak").textContent = state.streak;
|
||||||
|
var flame = document.getElementById("flameIcon");
|
||||||
|
flame.className = "";
|
||||||
|
if (state.combo >= 8) flame.className = "flame-high";
|
||||||
|
else if (state.combo >= 5) flame.className = "flame-mid";
|
||||||
|
else if (state.combo >= 3) flame.className = "flame-low";
|
||||||
}
|
}
|
||||||
function renderProgress() {
|
function renderProgress() {
|
||||||
var bar = document.getElementById("progressBar");
|
var bar = document.getElementById("progressBar");
|
||||||
@@ -455,6 +459,12 @@ function renderCombo() {
|
|||||||
"学富五车!",
|
"学富五车!",
|
||||||
"梅子无人能挡!",
|
"梅子无人能挡!",
|
||||||
"登峰造极!",
|
"登峰造极!",
|
||||||
|
"出口成章!",
|
||||||
|
"满腹经纶!",
|
||||||
|
"博古通今!",
|
||||||
|
"梅子开挂了!",
|
||||||
|
"无可匹敌!",
|
||||||
|
"梅子是成语王!",
|
||||||
];
|
];
|
||||||
var i = Math.min(Math.floor((state.combo - 3) / 2), msgs.length - 1);
|
var i = Math.min(Math.floor((state.combo - 3) / 2), msgs.length - 1);
|
||||||
var txt = "🔥 连击 ×" + state.combo + " " + msgs[i];
|
var txt = "🔥 连击 ×" + state.combo + " " + msgs[i];
|
||||||
@@ -477,6 +487,7 @@ function renderCombo() {
|
|||||||
function startRound() {
|
function startRound() {
|
||||||
state.round = 0;
|
state.round = 0;
|
||||||
state.roundResults = [];
|
state.roundResults = [];
|
||||||
|
state.usedIdiomIndices = {};
|
||||||
nextQuestion();
|
nextQuestion();
|
||||||
}
|
}
|
||||||
function nextQuestion() {
|
function nextQuestion() {
|
||||||
@@ -620,7 +631,19 @@ function showResult(ok, nc) {
|
|||||||
'"><h3 style="color:' +
|
'"><h3 style="color:' +
|
||||||
(ok ? "var(--green)" : "var(--red)") +
|
(ok ? "var(--green)" : "var(--red)") +
|
||||||
'">' +
|
'">' +
|
||||||
(ok ? "✅ 回答正确!" : "❌ 答错了~") +
|
(ok ? [
|
||||||
|
"✅ 回答正确!",
|
||||||
|
"✅ 太棒了!",
|
||||||
|
"✅ 梅子答对了!",
|
||||||
|
"✅ 完全正确!",
|
||||||
|
"✅ 厉害!",
|
||||||
|
"✅ 对!梅子真棒!",
|
||||||
|
][Math.floor(Math.random() * 6)] : [
|
||||||
|
"❌ 答错了~",
|
||||||
|
"❌ 没关系,记住它!",
|
||||||
|
"❌ 这次没中,下次加油!",
|
||||||
|
"❌ 差一点点~",
|
||||||
|
][Math.floor(Math.random() * 4)]) +
|
||||||
(ok && state.combo >= 3 ? " 🔥" : "") +
|
(ok && state.combo >= 3 ? " 🔥" : "") +
|
||||||
'</h3><div class="idiom-word">' +
|
'</h3><div class="idiom-word">' +
|
||||||
idiom.w +
|
idiom.w +
|
||||||
@@ -642,10 +665,25 @@ function finishRound() {
|
|||||||
state.reviewMode = false;
|
state.reviewMode = false;
|
||||||
var msg =
|
var msg =
|
||||||
c === ROUND_SIZE
|
c === ROUND_SIZE
|
||||||
? "满分!梅子太厉害了!🎉"
|
? [
|
||||||
|
"满分!梅子太厉害了!🎉",
|
||||||
|
"完美!梅子真是成语达人!✨",
|
||||||
|
"全对!梅子今天状态绝佳!🌟",
|
||||||
|
"漂亮!一题不差,梅子威武!👏",
|
||||||
|
][Math.floor(Math.random() * 4)]
|
||||||
: c >= 3
|
: c >= 3
|
||||||
? "梅子表现不错!继续加油~"
|
? [
|
||||||
: "没关系梅子,多练习就会进步!💪";
|
"梅子表现不错!继续加油~",
|
||||||
|
"答得很好,梅子越来越厉害了!",
|
||||||
|
"不错不错,梅子进步了!🌸",
|
||||||
|
"梅子答题越来越顺了,加油!",
|
||||||
|
][Math.floor(Math.random() * 4)]
|
||||||
|
: [
|
||||||
|
"没关系梅子,多练习就会进步!💪",
|
||||||
|
"继续努力,梅子肯定能行!",
|
||||||
|
"不怕不怕,熟能生巧!加油梅子~",
|
||||||
|
"错了没关系,下次梅子一定更好!",
|
||||||
|
][Math.floor(Math.random() * 4)];
|
||||||
var reviewBtn =
|
var reviewBtn =
|
||||||
wasReview && state.wrongBook.length
|
wasReview && state.wrongBook.length
|
||||||
? '<button class="action-btn secondary" onclick="showWrongBookModal()" style="margin-top:8px;width:100%">再次练习错题 📖</button>'
|
? '<button class="action-btn secondary" onclick="showWrongBookModal()" style="margin-top:8px;width:100%">再次练习错题 📖</button>'
|
||||||
@@ -743,11 +781,11 @@ function init() {
|
|||||||
loadState();
|
loadState();
|
||||||
loadWrongBook();
|
loadWrongBook();
|
||||||
renderWbBadge();
|
renderWbBadge();
|
||||||
if (state.bigFont) document.body.classList.add("big-font");
|
document.documentElement.setAttribute("data-theme", state.theme);
|
||||||
document.getElementById("btnSound").classList.toggle("active", state.sound);
|
document.getElementById("btnSound").classList.toggle("active", state.sound);
|
||||||
document.getElementById("btnSound").textContent = state.sound ? "🔊" : "🔇";
|
document.getElementById("btnSound").textContent = state.sound ? "🔊" : "🔇";
|
||||||
if (state.bigFont)
|
document.getElementById("btnTheme").textContent = state.theme === "ink" ? "🌙" : "☀️";
|
||||||
document.getElementById("btnBigFont").classList.add("active");
|
showThemeTooltip();
|
||||||
document.querySelectorAll(".diff-btn").forEach(function (b) {
|
document.querySelectorAll(".diff-btn").forEach(function (b) {
|
||||||
b.classList.toggle("active", +b.dataset.diff === state.difficulty);
|
b.classList.toggle("active", +b.dataset.diff === state.difficulty);
|
||||||
});
|
});
|
||||||
@@ -761,10 +799,29 @@ document.getElementById("btnSound").addEventListener("click", function () {
|
|||||||
this.textContent = state.sound ? "🔊" : "🔇";
|
this.textContent = state.sound ? "🔊" : "🔇";
|
||||||
saveState();
|
saveState();
|
||||||
});
|
});
|
||||||
document.getElementById("btnBigFont").addEventListener("click", function () {
|
function showThemeTooltip() {
|
||||||
state.bigFont = !state.bigFont;
|
if (localStorage.getItem("chengyu_theme_tip")) return;
|
||||||
document.body.classList.toggle("big-font", state.bigFont);
|
var tip = document.getElementById("themeTooltip");
|
||||||
this.classList.toggle("active", state.bigFont);
|
if (!tip) return;
|
||||||
|
setTimeout(function () {
|
||||||
|
tip.classList.add("show");
|
||||||
|
var timer = setTimeout(dismissThemeTooltip, 5000);
|
||||||
|
tip.addEventListener("click", function () {
|
||||||
|
clearTimeout(timer);
|
||||||
|
dismissThemeTooltip();
|
||||||
|
}, { once: true });
|
||||||
|
}, 1200);
|
||||||
|
}
|
||||||
|
function dismissThemeTooltip() {
|
||||||
|
var tip = document.getElementById("themeTooltip");
|
||||||
|
if (tip) tip.classList.remove("show");
|
||||||
|
localStorage.setItem("chengyu_theme_tip", "1");
|
||||||
|
}
|
||||||
|
document.getElementById("btnTheme").addEventListener("click", function () {
|
||||||
|
dismissThemeTooltip();
|
||||||
|
state.theme = state.theme === "ink" ? "paper" : "ink";
|
||||||
|
document.documentElement.setAttribute("data-theme", state.theme);
|
||||||
|
this.textContent = state.theme === "ink" ? "🌙" : "☀️";
|
||||||
saveState();
|
saveState();
|
||||||
});
|
});
|
||||||
document
|
document
|
||||||
|
|||||||
16
index.html
16
index.html
@@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN" data-theme="ink">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta
|
<meta
|
||||||
@@ -21,7 +21,13 @@
|
|||||||
<div class="header-title">梅子的成语填字</div>
|
<div class="header-title">梅子的成语填字</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<button class="icon-btn" id="btnSound">🔊</button>
|
<button class="icon-btn" id="btnSound">🔊</button>
|
||||||
<button class="icon-btn" id="btnBigFont">字</button>
|
<div class="theme-btn-wrap" id="themeBtnWrap">
|
||||||
|
<button class="icon-btn" id="btnTheme" title="切换主题">🌙</button>
|
||||||
|
<div class="theme-tooltip" id="themeTooltip">
|
||||||
|
新!点我切换白天/夜间模式 ✨
|
||||||
|
<div class="theme-tooltip-arrow"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button class="icon-btn" id="btnCheckin">📅</button>
|
<button class="icon-btn" id="btnCheckin">📅</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -29,7 +35,7 @@
|
|||||||
<div class="info-item">今日 <span id="statScore">0</span>分</div>
|
<div class="info-item">今日 <span id="statScore">0</span>分</div>
|
||||||
<div class="info-divider"></div>
|
<div class="info-divider"></div>
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
🔥 <span id="statCombo">0</span> 连击
|
<span id="flameIcon">🔥</span> <span id="statCombo">0</span> 连击
|
||||||
</div>
|
</div>
|
||||||
<div class="info-divider"></div>
|
<div class="info-divider"></div>
|
||||||
<div class="info-item info-wb" id="btnWrongBook">
|
<div class="info-item info-wb" id="btnWrongBook">
|
||||||
@@ -65,7 +71,7 @@
|
|||||||
<div class="modal">
|
<div class="modal">
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
style="background: linear-gradient(135deg, #6b4f2a, #c8941a)"
|
style=""
|
||||||
>
|
>
|
||||||
<div class="streak-display" id="wbCount">0</div>
|
<div class="streak-display" id="wbCount">0</div>
|
||||||
<div class="streak-label">道错题待复习 📖</div>
|
<div class="streak-label">道错题待复习 📖</div>
|
||||||
@@ -86,7 +92,7 @@
|
|||||||
<div class="modal">
|
<div class="modal">
|
||||||
<div
|
<div
|
||||||
class="modal-header"
|
class="modal-header"
|
||||||
style="background: linear-gradient(135deg, #2a7a52, #4caf50)"
|
style=""
|
||||||
>
|
>
|
||||||
<div style="font-size: 2.2rem">🎉</div>
|
<div style="font-size: 2.2rem">🎉</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
Reference in New Issue
Block a user