本页面的其他翻译:
- en
- zh
输入型填空题模板
功能介绍
为了适应不同的应用场景,模板设计了几种语法。
跳过挖空
使用(())包裹的内容不参与挖空
指定挖空
使用[[]]语法表示该文段必须被挖空,并且在挖去这些文段后,才计算剩余的挖空率
指定随机挖空
有时候我们想背诵的诗句往往有强关联,比如满堂花醉三千客,一剑霜寒十四州,我们想背诵第一句,对第二句挖空,或者想背诵第二句而对第一句挖空,这时候可以使用[[满堂花醉三千客,|一剑霜寒十四州]],这个语法将对第一句或者第二句随机挖空
错误处理
为了方便用户和开发者交流,当用户把挖空率设置为999时,anki将输出挖空前的原始文本和挖空后的文本。你可以把这些信息粘贴在下面的评论区,开发者根据这些信息进行错误处理
源码
下面提供模板的源码。
正面
点击查看正面内容模板
点击查看正面内容模板
<div class="test"> </div> <div id="debug-panel" style="display: none; text-align: left; font-family: 'Consolas', monospace; font-size: 11px; background: #1a1a1a; color: #ddd; padding: 15px; margin-top: 20px; border-radius: 8px; border: 2px solid #444; overflow-x: auto;"> <div style="margin-bottom: 15px;"> </div> <div style="margin-bottom: 15px;"> </div> </div> <script type="text/javascript"> (function() { var sentenceArea = document.getElementById("sentence-area"); if (!sentenceArea) return; var rawRateStr = "{{text:挖空率}}".trim(); var rateNum = parseInt(rawRateStr.replace(/[^0-9]/g, "")); var isDebugMode = (rateNum === 999); var rate = isDebugMode ? 70 : (isNaN(rateNum) ? 70 : rateNum); var rawContent = sentenceArea.innerText || sentenceArea.textContent; // 1. 强化正则:非贪婪匹配 [[...]] 和 ((...)),优先捕获 var complexRegex = /\(\([\s\S]*?\)\)|\[\[[\s\S]*?\]\]|\n|\r|[^\S\n\r]+|[a-zA-Z0-9-']+|[\u4e00-\u9fa5]|./g; var allUnits = []; var mandatoryIndices = []; var optionalIndices = []; var match; // 标点符号黑名单:确保这些字符绝不挖空 var puncBlacklist = /[,。!?;:、“”()《》…—·\[\]\(\)\{\}\s\t\r\n]/; while ((match = complexRegex.exec(rawContent)) !== null) { var token = match[0]; if (token.startsWith("((")) { allUnits.push({ text: token.slice(2, -2), canBlank: false, isTarget: false, type: "protected" }); } else if (token.startsWith("[[")) { var inner = token.slice(2, -2); if (inner.indexOf("|") !== -1) { var parts = inner.split("|"); var randIndex = Math.random() < 0.5 ? 0 : 1; parts.forEach(function(p, idx) { var isBlank = (idx === randIndex); if (isBlank) mandatoryIndices.push(allUnits.length); allUnits.push({ text: p, canBlank: isBlank, isTarget: isBlank, isLogicGroup: true }); }); } else { mandatoryIndices.push(allUnits.length); allUnits.push({ text: inner, canBlank: true, isTarget: false }); } } else if (token === "\n" || token === "\r") { allUnits.push({ text: token, canBlank: false, isTarget: false, isNewline: true }); } else { var isWordOrNum = /[a-zA-Z0-9\u4e00-\u9fa5]/.test(token); var isDe = /^[的是了有]$/.test(token); // 关键:排除黑名单中的标点符号 var isPunctuation = puncBlacklist.test(token); var canBlank = isWordOrNum && !isDe && !isPunctuation; if (canBlank) optionalIndices.push(allUnits.length); allUnits.push({ text: token, canBlank: canBlank, isTarget: false }); } } var totalPotential = mandatoryIndices.length + optionalIndices.length; var globalQuota = Math.round(totalPotential * rate / 100); mandatoryIndices.forEach(function(idx) { allUnits[idx].isTarget = true; }); var neededMore = globalQuota - mandatoryIndices.length; if (neededMore > 0 && optionalIndices.length > 0) { var shuffled = optionalIndices.sort(function() { return 0.5 - Math.random(); }); shuffled.slice(0, neededMore).forEach(function(idx) { allUnits[idx].isTarget = true; }); } if (isDebugMode) { var debugPanel = document.getElementById("debug-panel"); if (debugPanel) { debugPanel.style.display = "block"; document.getElementById("debug-raw-html").innerText = rawContent; document.getElementById("debug-tokens").innerHTML = allUnits.map(u => { let color = u.isTarget ? "#0f0" : (u.canBlank ? "#777" : "#f44"); }).join(""); document.getElementById("debug-stats").innerText = `统计:手动/组挖空 ${mandatoryIndices.length} | 随机库 ${optionalIndices.length} | 选中总计 ${allUnits.filter(u=>u.isTarget).length}`; } } var finalHtml = ""; for (var k = 0; k < allUnits.length; k++) { var curr = allUnits[k]; if (curr.isTarget) { var combinedText = curr.text; if (!curr.isLogicGroup) { while (k + 1 < allUnits.length && allUnits[k+1].isTarget && !allUnits[k+1].isNewline && !allUnits[k+1].isLogicGroup) { combinedText += allUnits[k+1].text; k++; } } var isCN = /[\u4e00-\u9fa5]/.test(combinedText); var width = isCN ? (combinedText.length * 28 + 15) : (combinedText.length * 12 + 18); finalHtml += '<input type="text" class="answer-box" style="width:' + width + 'px" data="' + combinedText + '" autocomplete="off" spellcheck="false"/>'; } else { finalHtml += curr.isNewline ? "<br>" : curr.text; } } sentenceArea.innerHTML = finalHtml; var ipts = Array.from(sentenceArea.getElementsByTagName("input")); if (ipts.length > 0) { ipts[0].focus(); ipts.forEach(function(ab, idx) { ab.addEventListener('input', function() { check(this, idx); }); ab.addEventListener('keydown', function(e) { if (e.keyCode === 13 && ipts[idx+1]) ipts[idx+1].focus(); if (e.keyCode === 8 && this.value === "" && idx > 0) { var prev = idx - 1; while(prev >= 0 && ipts[prev].readOnly) prev--; if(prev >= 0) ipts[prev].focus(); } }); }); function check(el, i) { var target = el.getAttribute("data").toLowerCase(); var val = el.value.trim().toLowerCase(); if (val === target) { el.className = "answer-box right-answer"; el.value = el.getAttribute("data"); el.readOnly = true; el.blur(); if (ipts[i + 1]) ipts[i + 1].focus(); } else if (val.length > 0 && target.indexOf(val) !== 0) { el.className = "answer-box wrong-answer"; } else { el.className = "answer-box"; } } } })(); </script>
背面
点击查看背面内容模板
点击查看背面内容模板
<div class="test"> <div class="translation"> {{text:语言}} </div> <div class="sentence" id="sentence-area">{{text:文段}}</div> </div> {{#笔记}} <hr> <div class="note">{{笔记}}</div> {{/笔记}} <script type="text/javascript"> var sentenceArea = document.getElementById("sentence-area"); if (sentenceArea) { var html = sentenceArea.innerHTML; // 1. 处理互斥组 [[A|B]] -> 还原为 AB html = html.replace(/\[\[(.*?)\|(.*?)\]\]/g, "$1$2"); // 2. 处理强制组 [[A]] -> 还原为 A // 注意:这里使用了循环匹配,防止连续的 [[A]][[B]] 导致漏删括号 while (html.indexOf("[[") !== -1 || html.indexOf("]]") !== -1) { html = html.replace(/\[\[(.*?)\]\]/g, "$1"); // 兜底:清理掉可能残余的孤立括号 html = html.replace(/\[\[/g, "").replace(/\]\]/g, ""); } // 3. 处理保护区 ((A)) -> 还原为 A html = html.replace(/\(\((.*?)\)\)/g, "$1"); // 4. 处理普通括号 (A) -> 还原为 A html = html.replace(/\(|\)/g, ""); sentenceArea.innerHTML = html; } </script>
样式
点击查看样式
点击查看样式
@import url('https://cdn.jsdelivr.net/npm/lxgw-wenkai-screen-web/style.css?cache=1y'); .card { font-family: "LXGW WenKai Screen","PingFang SC", "Microsoft YaHei", arial, sans-serif; font-size: 20px; color: #333; background-color: white; padding: 15px; line-height: 1.6; } .sentence { font-size: 26px; margin: 20px 0; line-height: 2.2; /* 增加行高,给长输入框留出空间 */ text-align: justify; } /* 核心:输入框样式优化 */ .answer-box { border: none; border-bottom: 2px solid #000; /* 加粗底线,更有辨识度 */ background-color: #f8f9fa; /* 淡淡的底色,让长格子一眼可见范围 */ text-align: center; outline: none; font-size: 26px; font-family: inherit; margin: 0 4px; padding: 0 5px; transition: all 0.2s; max-width: 95%; /* 关键:防止超长句子在手机上横向溢出 */ border-radius: 4px 4px 0 0; } /* 聚焦时的视觉反馈 */ .answer-box:focus { background-color: #e9ecef; border-bottom-color: #007bff; /* 聚焦时底线变蓝 */ } .right-answer { color: #28a745 !important; background-color: #e8f5e9 !important; border-bottom-color: #28a745 !important; } .wrong-answer { color: #dc3545 !important; background-color: #ffebee !important; border-bottom-color: #dc3545 !important; } .title { font-size: 32px; font-weight: bold; text-align: center; margin-bottom: 10px; } .author { font-size: 18px; color: #666; text-align: center; margin-bottom: 20px; } .translation { font-size: 20px; margin: 10px 0; color: #555; border-left: 4px solid #ddd; padding-left: 10px; }
下载
为方便用户,本站提供导出的牌组下载
zh/anki/cardtemplate/输入型填空题模板.txt · 最后更改: 由 tom



评论