// 每个分区内容区顶部内边距(px) export const SECTION_PADDING_TOP = 12; // 每个分区内容区底部内边距(px) export const SECTION_PADDING_BOTTOM = 10; // 标题与上一元素的垂直间距(px) export const HEADER_TITLE_GAP = 32; // 标题与元信息(如日期、学号等)的间距(px) export const HEADER_META_GAP = 22; // 正文内容距标题/元信息顶部的间距(px) export const CONTENT_TOP_GAP = 14; // 页脚短语与内容之间的间距(px) export const FOOTER_PHRASE_GAP = 26; // 页脚索引与短语之间的间距(px) export const FOOTER_INDEX_GAP = 22; // 20 条鼓励语词库 export const ENCOURAGEMENT_PHRASES: ReadonlyArray = [ '书山有路勤为径', '日拱一卒 不期而至', '宝剑锋从磨砺出', '梅花香自苦寒来', '业精于勤荒于嬉', '行百里者半九十', '锲而不舍金石可镂', '读万卷书行万里路', '滴水穿石非一日之功', '天下无难事只怕有心人', '熟能生巧功到自然成', '敏而好学不耻下问', '学而不思则罔', '思而不学则殆', '欲速则不达', '不积跬步无以至千里', '不积小流无以成江海', '温故而知新', '读书破万卷下笔如有神', '千里之行始于足下', ]; /** * 随机获取一条鼓励语 */ export function getRandomEncouragementPhrase(): string { const idx = Math.floor(Math.random() * ENCOURAGEMENT_PHRASES.length); return ENCOURAGEMENT_PHRASES[idx]; } /** * 绘制统一的每日练习每个 Section 中的 Header * @param ctx 微信小程序 Canvas 绘制上下文 * @param rect 目标 Section 的位置与宽高信息 * @param title 标题文本,如 “每日打卡” 或 “拼音每日一练” */ export function drawSectionHeader( ctx: RenderingContext, rect: { x: number; y: number; w: number; h: number }, title: string, ): void { const cx = rect.x + rect.w / 2; const titleY = rect.y + SECTION_PADDING_TOP + 12; const metaY = titleY + HEADER_TITLE_GAP; const metaUnderlineY = metaY + 5; const canvasCtx = ctx as any; canvasCtx.save(); canvasCtx.fillStyle = '#322E25'; canvasCtx.textAlign = 'center'; canvasCtx.textBaseline = 'middle'; // 字体样式与 dailyCheckinDraw.ts 保持一致 canvasCtx.font = '20px serif'; canvasCtx.fillText(title, cx, titleY); canvasCtx.font = '12px serif'; canvasCtx.fillText('月', rect.x + 76, metaY); canvasCtx.fillText('日', rect.x + 122, metaY); canvasCtx.fillText('姓名:', rect.x + 176, metaY); canvasCtx.strokeStyle = '#8E897E'; canvasCtx.lineWidth = 1; canvasCtx.setLineDash([]); canvasCtx.beginPath(); canvasCtx.moveTo(rect.x + 40, metaUnderlineY); canvasCtx.lineTo(rect.x + 68, metaUnderlineY); canvasCtx.moveTo(rect.x + 85, metaUnderlineY); canvasCtx.lineTo(rect.x + 113, metaUnderlineY); canvasCtx.moveTo(rect.x + 195, metaUnderlineY); canvasCtx.lineTo(rect.x + 248, metaUnderlineY); canvasCtx.stroke(); canvasCtx.restore(); } /** * 绘制统一的每日练习每个 Section 中的 Footer * @param ctx 微信小程序 Canvas 绘制上下文 * @param rect 目标 Section 的位置与宽高信息 * @param phrase 鼓励语文本 * @param labelText 页面/天数索引文本,如 “- 1 -” 或 “第 1 天” */ export function drawSectionFooter( ctx: RenderingContext, rect: { x: number; y: number; w: number; h: number }, phrase: string, labelText: string, ): void { const cx = rect.x + rect.w / 2; const phraseY = rect.y + rect.h - SECTION_PADDING_BOTTOM - FOOTER_PHRASE_GAP; const indexY = rect.y + rect.h - SECTION_PADDING_BOTTOM - 6; const canvasCtx = ctx as any; canvasCtx.save(); canvasCtx.fillStyle = '#3E3A33'; canvasCtx.textAlign = 'center'; canvasCtx.textBaseline = 'middle'; // 字体样式与 dailyCheckinDraw.ts 保持一致 canvasCtx.font = '14px serif'; canvasCtx.fillText(phrase, cx, phraseY); canvasCtx.font = '12px serif'; canvasCtx.fillText(labelText, cx, indexY); canvasCtx.restore(); }