refactor: 完全重构为 Anki 兼容数据结构

- 用 Deck 替换 Folder
- 用 Note + Card 替换 Pair (双向复习)
- 添加 NoteType (卡片模板)
- 添加 Revlog (复习历史)
- 实现 SM-2 间隔重复算法
- 更新所有前端页面
- 添加数据库迁移
This commit is contained in:
2026-03-10 19:20:46 +08:00
parent 9b78fd5215
commit 57ad1b8699
72 changed files with 7107 additions and 2430 deletions

View File

@@ -169,22 +169,46 @@
"resetPasswordSuccessHint": "您的密码已成功重置,现在可以使用新密码登录了。"
},
"memorize": {
"folder_selector": {
"selectFolder": "选择文件夹",
"noFolders": "未找到文件夹",
"folderInfo": "{id}. {name} ({count})"
"deck_selector": {
"selectDeck": "选择牌组",
"noDecks": "未找到牌组",
"goToDecks": "前往牌组",
"noCards": "无卡片",
"new": "新卡片",
"learning": "学习中",
"review": "复习",
"due": "待复习"
},
"memorize": {
"answer": "答案",
"next": "下一个",
"reverse": "反向",
"dictation": "听写",
"noTextPairs": "没有可用的文本对",
"disorder": "乱序",
"previous": "上一个"
"review": {
"loading": "加载中...",
"backToDecks": "返回牌组",
"allDone": "全部完成!",
"allDoneDesc": "您已完成所有待复习卡片。",
"reviewedCount": "已复习 {count} 张卡片",
"progress": "{current} / {total}",
"nextReview": "下次复习",
"interval": "间隔",
"ease": "难度系数",
"lapses": "遗忘次数",
"showAnswer": "显示答案",
"again": "重来",
"hard": "困难",
"good": "良好",
"easy": "简单",
"now": "现在",
"lessThanMinute": "<1 分钟",
"inMinutes": "{count} 分钟",
"inHours": "{count} 小时",
"inDays": "{count} 天",
"inMonths": "{count} 个月",
"minutes": "<1 分钟",
"days": "{count} 天",
"months": "{count} 个月",
"minAbbr": "分",
"dayAbbr": "天"
},
"page": {
"unauthorized": "您无权访问该文件夹"
"unauthorized": "您无权访问该牌组"
}
},
"navbar": {
@@ -200,31 +224,45 @@
"ocr": {
"title": "OCR 词汇提取",
"description": "上传教材词汇表截图,提取单词-释义对",
"uploadSection": "上传图片",
"uploadImage": "上传图片",
"dragDropHint": "拖放图片到此处,或点击选择",
"dropOrClick": "拖放图片到此处,或点击选择",
"changeImage": "点击更换图片",
"supportedFormats": "支持格式JPG、PNG、WebP",
"selectFolder": "选择文件夹",
"chooseFolder": "选择保存提取词汇的文件夹",
"noFolders": "暂无文件夹,请先创建文件夹",
"deckSelection": "选择牌组",
"selectDeck": "选择牌组",
"chooseDeck": "选择保存提取词汇的牌组",
"noDecks": "暂无牌组,请先创建牌组",
"languageHints": "语言提示(可选)",
"sourceLanguageHint": "源语言(如:英语)",
"targetLanguageHint": "目标/翻译语言(如:中文)",
"sourceLanguagePlaceholder": "源语言(如:英语)",
"targetLanguagePlaceholder": "目标/翻译语言(如:中文)",
"process": "处理图片",
"processButton": "处理图片",
"processing": "处理中...",
"preview": "预览",
"extractedPairs": "提取的词汇对",
"resultsPreview": "结果预览",
"extractedPairs": "已提取 {count} 个词汇对",
"word": "单词",
"definition": "释义",
"pairsCount": "已提取 {count} 个词汇对",
"savePairs": "保存到文件夹",
"pairsCount": "{count} 个词汇对",
"savePairs": "保存到牌组",
"saveButton": "保存",
"saving": "保存中...",
"saved": "成功将 {count} 个词汇对保存到 {folder}",
"saved": "成功将 {count} 个词汇对保存到 {deck}",
"ocrSuccess": "成功将 {count} 个词汇对保存到 {deck}",
"savedToDeck": "已保存到 {deckName}",
"saveFailed": "保存失败",
"noImage": "请先上传图片",
"noFolder": "请选择文件夹",
"noDeck": "请选择牌组",
"noResultsToSave": "没有可保存的结果",
"processingFailed": "OCR 处理失败",
"tryAgain": "请尝试上传更清晰的图片",
"detectedLanguages": "检测到:{source} → {target}"
"detectedLanguages": "检测到:{source} → {target}",
"detectedSourceLanguage": "检测到的源语言",
"detectedTargetLanguage": "检测到的目标语言"
},
"profile": {
"myProfile": "我的个人资料",
@@ -338,11 +376,11 @@
},
"explore": {
"title": "探索",
"subtitle": "发现公开文件夹",
"searchPlaceholder": "搜索公开文件夹...",
"subtitle": "发现公开牌组",
"searchPlaceholder": "搜索公开牌组...",
"loading": "加载中...",
"noFolders": "没有找到公开文件夹",
"folderInfo": "{userName} • {totalPairs} 个文本对",
"noDecks": "没有找到公开牌组",
"deckInfo": "{userName} • {cardCount} 张卡片",
"unknownUser": "未知用户",
"favorite": "收藏",
"unfavorite": "取消收藏",
@@ -351,10 +389,10 @@
"sortByFavoritesActive": "取消按收藏数排序"
},
"exploreDetail": {
"title": "文件夹详情",
"title": "牌组详情",
"createdBy": "创建者:{name}",
"unknownUser": "未知用户",
"totalPairs": "词对数量",
"totalCards": "卡片数量",
"favorites": "收藏数",
"createdAt": "创建时间",
"viewContent": "查看内容",
@@ -385,11 +423,11 @@
"memberSince": "注册时间",
"joined": "加入于",
"logout": "登出",
"folders": {
"title": "文件夹",
"noFolders": "还没有文件夹",
"folderName": "文件夹名称",
"totalPairs": "文本对数量",
"decks": {
"title": "牌组",
"noDecks": "还没有牌组",
"deckName": "牌组名称",
"totalCards": "卡片数量",
"createdAt": "创建时间",
"actions": "操作",
"view": "查看"