Refactor code structure for improved readability and maintainability
All checks were successful
Deploy / deploy (push) Successful in 2s

This commit is contained in:
M1ngdaXie
2026-03-27 01:39:09 -07:00
parent db30afb035
commit fc1eb2040c
4 changed files with 742 additions and 573 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.superpowers

103
app.js
View File

@@ -93,7 +93,7 @@ function sfxComplete() {
const APP_VERSION = 2;
var state = {
sound: true,
bigFont: false,
theme: "ink",
difficulty: 1,
score: 0,
combo: 0,
@@ -123,7 +123,7 @@ function saveState() {
"chengyu_s",
JSON.stringify({
sound: state.sound,
bigFont: state.bigFont,
theme: state.theme,
difficulty: state.difficulty,
totalCount: state.totalCount,
streak: state.streak,
@@ -237,7 +237,7 @@ function loadState() {
try {
var s = JSON.parse(localStorage.getItem("chengyu_s") || "{}");
state.sound = s.sound !== undefined ? s.sound : true;
state.bigFont = s.bigFont || false;
state.theme = s.theme || "ink";
state.totalCount = s.totalCount || 0;
state.streak = s.streak || 0;
state.checkinDays = s.checkinDays || [];
@@ -312,16 +312,15 @@ function pickIdiom() {
return item;
}
var pool = IDIOMS.filter(function (i) {
return i.l <= state.difficulty;
return i.l <= state.difficulty && !state.usedIdiomIndices[i.w];
});
var a = 0,
idx;
do {
idx = Math.floor(Math.random() * pool.length);
a++;
} while (state.usedIdiomIndices[pool[idx].w] && a < 100);
state.usedIdiomIndices[pool[idx].w] = 1;
return pool[idx];
if (!pool.length) {
state.usedIdiomIndices = {};
pool = IDIOMS.filter(function (i) { return i.l <= state.difficulty; });
}
var item = pool[Math.floor(Math.random() * pool.length)];
state.usedIdiomIndices[item.w] = 1;
return item;
}
function generateBlanks(w, d) {
var n = d === 1 ? 1 : d === 2 ? 2 : 3;
@@ -375,6 +374,11 @@ function renderStats() {
document.getElementById("statCombo").textContent = state.combo;
document.getElementById("statTotal").textContent = state.totalCount;
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() {
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 txt = "🔥 连击 ×" + state.combo + " " + msgs[i];
@@ -477,6 +487,7 @@ function renderCombo() {
function startRound() {
state.round = 0;
state.roundResults = [];
state.usedIdiomIndices = {};
nextQuestion();
}
function nextQuestion() {
@@ -620,7 +631,19 @@ function showResult(ok, nc) {
'"><h3 style="color:' +
(ok ? "var(--green)" : "var(--red)") +
'">' +
(ok ? "✅ 回答正确!" : "❌ 答错了~") +
(ok ? [
"✅ 回答正确!",
"✅ 太棒了!",
"✅ 梅子答对了!",
"✅ 完全正确!",
"✅ 厉害!",
"✅ 对!梅子真棒!",
][Math.floor(Math.random() * 6)] : [
"❌ 答错了~",
"❌ 没关系,记住它!",
"❌ 这次没中,下次加油!",
"❌ 差一点点~",
][Math.floor(Math.random() * 4)]) +
(ok && state.combo >= 3 ? " 🔥" : "") +
'</h3><div class="idiom-word">' +
idiom.w +
@@ -642,10 +665,25 @@ function finishRound() {
state.reviewMode = false;
var msg =
c === ROUND_SIZE
? "满分!梅子太厉害了!🎉"
? [
"满分!梅子太厉害了!🎉",
"完美!梅子真是成语达人!✨",
"全对!梅子今天状态绝佳!🌟",
"漂亮!一题不差,梅子威武!👏",
][Math.floor(Math.random() * 4)]
: c >= 3
? "梅子表现不错!继续加油~"
: "没关系梅子,多练习就会进步!💪";
? [
"梅子表现不错!继续加油~",
"答得很好,梅子越来越厉害了!",
"不错不错,梅子进步了!🌸",
"梅子答题越来越顺了,加油!",
][Math.floor(Math.random() * 4)]
: [
"没关系梅子,多练习就会进步!💪",
"继续努力,梅子肯定能行!",
"不怕不怕,熟能生巧!加油梅子~",
"错了没关系,下次梅子一定更好!",
][Math.floor(Math.random() * 4)];
var reviewBtn =
wasReview && state.wrongBook.length
? '<button class="action-btn secondary" onclick="showWrongBookModal()" style="margin-top:8px;width:100%">再次练习错题 📖</button>'
@@ -743,11 +781,11 @@ function init() {
loadState();
loadWrongBook();
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").textContent = state.sound ? "🔊" : "🔇";
if (state.bigFont)
document.getElementById("btnBigFont").classList.add("active");
document.getElementById("btnTheme").textContent = state.theme === "ink" ? "🌙" : "☀️";
showThemeTooltip();
document.querySelectorAll(".diff-btn").forEach(function (b) {
b.classList.toggle("active", +b.dataset.diff === state.difficulty);
});
@@ -761,10 +799,29 @@ document.getElementById("btnSound").addEventListener("click", function () {
this.textContent = state.sound ? "🔊" : "🔇";
saveState();
});
document.getElementById("btnBigFont").addEventListener("click", function () {
state.bigFont = !state.bigFont;
document.body.classList.toggle("big-font", state.bigFont);
this.classList.toggle("active", state.bigFont);
function showThemeTooltip() {
if (localStorage.getItem("chengyu_theme_tip")) return;
var tip = document.getElementById("themeTooltip");
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();
});
document

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="zh-CN">
<html lang="zh-CN" data-theme="ink">
<head>
<meta charset="UTF-8" />
<meta
@@ -21,7 +21,13 @@
<div class="header-title">梅子的成语填字</div>
<div class="header-right">
<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>
</div>
</div>
@@ -29,7 +35,7 @@
<div class="info-item">今日&nbsp;<span id="statScore">0</span></div>
<div class="info-divider"></div>
<div class="info-item">
🔥&nbsp;<span id="statCombo">0</span>&nbsp;连击
<span id="flameIcon">🔥</span>&nbsp;<span id="statCombo">0</span>&nbsp;连击
</div>
<div class="info-divider"></div>
<div class="info-item info-wb" id="btnWrongBook">
@@ -65,7 +71,7 @@
<div class="modal">
<div
class="modal-header"
style="background: linear-gradient(135deg, #6b4f2a, #c8941a)"
style=""
>
<div class="streak-display" id="wbCount">0</div>
<div class="streak-label">道错题待复习 📖</div>
@@ -86,7 +92,7 @@
<div class="modal">
<div
class="modal-header"
style="background: linear-gradient(135deg, #2a7a52, #4caf50)"
style=""
>
<div style="font-size: 2.2rem">🎉</div>
<div

1177
style.css

File diff suppressed because it is too large Load Diff