feat: Add Learn-Number tool for preschool math practice and refactor HTML components
Build and Push Docker Image / build (push) Successful in 2m55s

This commit is contained in:
2026-02-25 19:22:58 -08:00
parent e320f9ee50
commit 0be94026c5
9 changed files with 396 additions and 82 deletions
+44 -71
View File
@@ -1,51 +1,10 @@
{{define "content"}}
<!-- 汉字字帖面板 -->
<div id="panel-zitie" class="tool-panel">
<header class="page-header">
<h1>汉字字帖生成器</h1>
<p>生成高颜值的硬笔/毛笔书法练习帖,支持 A4/Letter 高清矢量打印。</p>
</header>
<div class="tabs-container">
<div id="tab-teaching" class="tab-btn active" onclick="switchZitieTab('teaching')">2x3 教学方格</div>
<div id="tab-step" class="tab-btn" onclick="switchZitieTab('step')">步进式分解</div>
<div id="tab-manuscript" class="tab-btn" onclick="switchZitieTab('manuscript')">古风竖排</div>
</div>
<!-- 注入各个工具面板 -->
{{template "zitie" .}}
{{template "learn_number" .}}
<div class="card">
<div style="display: flex; flex-direction: column; gap: 24px;">
<div class="input-group">
<label id="input-label">输入汉字内容 (2x3 教学方格模式下标点将被自动过滤)</label>
<textarea id="chars" placeholder="支持多行输入...">永和九年,岁在癸丑。</textarea>
</div>
<div style="display: flex; gap: 20px; align-items: flex-end; flex-wrap: wrap;">
<div style="flex: 1; min-width: 200px;">
<label style="font-size: 13px; font-weight: 600; color: #86868b; display: block; margin-bottom: 8px;">纸张大小</label>
<select id="paper_size">
<option value="A4">A4 (210x297mm)</option>
<option value="Letter">Letter (8.5x11in)</option>
</select>
</div>
<div id="font-select-group" style="flex: 1; min-width: 200px; display: none;">
<label style="font-size: 13px; font-weight: 600; color: #86868b; display: block; margin-bottom: 8px;">书法字体</label>
<select id="font_type">
<option value="kaiti">华光楷体</option>
<option value="xingshu">华光行草</option>
<option value="lishu">华光隶变</option>
<option value="songti">华光书宋</option>
</select>
</div>
<button onclick="generatePDF()">生成高清预览</button>
</div>
</div>
</div>
<div id="pdf-preview-container" style="display:none; width: 100%; height: 850px; border-radius: 20px; overflow: hidden; box-shadow: 0 10px 40px rgba(0,0,0,0.1); background: #fff; border: 1px solid #d2d2d7;">
<iframe id="pdf-frame" style="width: 100%; height: 100%; border: none;"></iframe>
</div>
</div>
<!-- 默认欢迎面板 -->
<!-- 欢迎面板 -->
<div id="panel-welcome" class="tool-panel">
<header class="page-header">
<h1>欢迎使用个人工具箱</h1>
@@ -55,53 +14,67 @@
<div style="margin-top: 40px; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px;">
<div class="card" style="cursor:pointer; transition: transform 0.2s;" onmouseover="this.style.transform='translateY(-5px)'" onmouseout="this.style.transform='translateY(0)'" onclick="navigateTo('/zitie')">
<h3 style="margin-top:0;">🖋️ 汉字字帖生成</h3>
<p style="color: #86868b; line-height: 1.5;">支持多种书法字体的 2x3 教学方格、步进分解和古风竖排信纸。专为硬笔和毛笔练习设计。</p>
<p style="color: #86868b; line-height: 1.5;">支持多种书法字体的 2x3 教学方格、步进分解和古风竖排信纸。</p>
<div style="color: var(--apple-blue); font-weight: 600; margin-top: 16px;">立即开始 →</div>
</div>
<div class="card" style="cursor:pointer; transition: transform 0.2s;" onmouseover="this.style.transform='translateY(-5px)'" onmouseout="this.style.transform='translateY(0)'" onclick="navigateTo('/learn-number')">
<h3 style="margin-top:0;">🔢 幼儿数学助手</h3>
<p style="color: #86868b; line-height: 1.5;">数图形、基础算术等趣味练习。培养孩子的数感与逻辑。</p>
<div style="color: var(--apple-blue); font-weight: 600; margin-top: 16px;">立即开始 →</div>
</div>
</div>
</div>
<script>
let currentMode = 'teaching';
// --- Zitie Tool Logic ---
let currentZitieMode = 'teaching';
function switchZitieTab(mode) {
currentMode = mode;
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
currentZitieMode = mode;
document.querySelectorAll('#panel-zitie .tab-btn').forEach(btn => btn.classList.remove('active'));
document.getElementById(`tab-${mode}`).classList.add('active');
document.getElementById('font-select-group').style.display = (mode === 'manuscript') ? 'block' : 'none';
const labels = {
'teaching': '输入汉字内容 (2x3 教学方格模式下标点将被自动过滤)',
'step': '输入汉字内容 (步进式分解模式下标点将被自动过滤)',
'manuscript': '输入汉字内容 (古风竖排支持换行,标点将被过滤)'
};
document.getElementById('input-label').innerText = labels[mode];
}
async function generatePDF() {
async function generateZitiePDF() {
const chars = document.getElementById('chars').value;
const paper_size = document.getElementById('paper_size').value;
const font_type = document.getElementById('font_type').value;
const btn = document.querySelector('button');
const originalText = btn.innerText;
btn.innerText = '正在绘图中...'; btn.disabled = true;
const btn = document.querySelector('#panel-zitie button');
btn.innerText = '绘图中...'; btn.disabled = true;
try {
const response = await fetch(`/api/zitie/${currentMode}`, {
const response = await fetch(`/api/zitie/${currentZitieMode}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ chars, paper_size, font_type })
});
if (response.ok) {
const blob = await response.blob();
document.getElementById('pdf-preview-container').style.display = 'block';
document.getElementById('pdf-frame').src = URL.createObjectURL(blob);
if(window.innerWidth < 768) document.getElementById('pdf-preview-container').scrollIntoView({behavior: 'smooth'});
} else { alert('生成失败'); }
} catch (e) { alert('网络错误'); } finally {
btn.innerText = originalText;
btn.disabled = false;
}
document.getElementById('zitie-preview').style.display = 'block';
document.getElementById('zitie-frame').src = URL.createObjectURL(blob);
}
} catch (e) { alert('错误'); } finally { btn.innerText = '生成字帖预览'; btn.disabled = false; }
}
// --- Math Tool Logic ---
async function generateMathPDF() {
const total_count = parseInt(document.getElementById('total_count').value);
const icon_types = parseInt(document.getElementById('icon_types').value);
const paper_size = document.getElementById('math_paper_size').value;
const btn = document.querySelector('#panel-learn-number button');
btn.innerText = '生成中...'; btn.disabled = true;
try {
const response = await fetch('/api/learn-number/counting', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ total_count, icon_types, paper_size })
});
if (response.ok) {
const blob = await response.blob();
document.getElementById('math-preview').style.display = 'block';
document.getElementById('math-frame').src = URL.createObjectURL(blob);
if(window.innerWidth < 768) document.getElementById('math-preview').scrollIntoView({behavior: 'smooth'});
}
} catch (e) { alert('错误'); } finally { btn.innerText = '生成数学练习帖'; btn.disabled = false; }
}
</script>
{{end}}