返回顶部
学习鹅

学习鹅 - 学习时间管理助手

这是一款专为家庭设计的学习辅助应用。我希望能花更多时间妥善运用在孩子教育上。本项目源于一个简单的愿望:让親子教育更有质量,更有效率。

应用核心功能包含:

  • 基于番茄工作法的学习计时系统(45分钟学习,15分钟休息)
  • 语文听写练习工具
  • 英语听写练习工具
  • 中文词典 (拼音 & 部首)

goose-appstore-view

之所以想要开发这个 App 有很多方面因素吧

  • 想找个项目探索下 SwiftUI 开发,见见不一样的市面,AI 出来了后,让跨界快速开发成为可能。
  • 平时没有太多时间辅导小孩学习,等真的家里蹲着的时候,我又没有那个耐心,😄 那就做点擅长的事情送给孩子们吧。

项目后记

  • 感觉时间管理有用,但是没有那么有用,番茄工作法确实有效果,但是没有那么有效果。推广到小孩层面,可能需要更多耐心。产品上需要更多思考,而我可能没有那么多时间慢慢打磨。
  • 小孩长时间占用手机的担忧点
  • 时间管理 + 作业辅导,概念都揉在一起。如果想为了推出 AI 辅导,何不单独写个 App 呢?

这段旅途就先到这吧,👋

也许哪天它会以另外一种形式回来?

开发笔记 📝


定位:课后学习管理

待办作业 -> 时间管理 -> 完成 -> 作业批改 -> 统计回顾
			 |
			 ---> 卡点 工具 & AI 辅助

早期设计稿

goose-design-file

听写

  1. 同步课本资源,可以在 国家教育资源公共服务平台 上,找到相关的课本资源。
  2. PDF 文字提取,使用 Adobe Extract PDF 接口 工具,可以提取 PDF 中的文字。
  3. AI 整理并输出 JSON 数据 Google Gemini
  4. 生成应用所需要的 Sqlite 数据库。

提示词示例

I extracted some data from pdf, it is chinese textbook, contians char and pinyin
I will paste it to you

liAng 两 nA 哪 kuQn 宽 dJng顶 yAn眼

require you return json to me, format is like
{
  words: [
    { char: "两", pinyin: "liang" },
    { char: "哪", pinyin: "na" },
    { char: "宽", pinyin: "kuan" },
    { char: "顶", pinyin: "ding" },
    { char: "眼", pinyin: "yan" },
  ]
}

Please infer the pinyin field, all lower case。 

后来发现用 pinyin-pro 库,可以更方便的生成带声调的拼音。当然 AI 帮我转化格式确实帮了个大忙。👍

Apple 的 AVFoundation 框架,可以方便的播放音频,但是如果读字效果并不是特别好,所以在数据准备阶段的 拼音和音调格式和准确性尤其重要。

准备好数据源,通过文件目录结果来组织

vocabulary/
├── join in 三年级起点
│   ├── 三年级
│   │   └── 上册.json
│   ├── 五年级
│   │   ├── 上册.json
│   │   └── 下册.json
│   ├── 六年级
│   │   ├── 上册.json
│   │   └── 下册.json
│   └── 四年级
│       ├── 上册.json
│       └── 下册.json
└── 语文(统编版)
    ├── 一年级
    │   ├── 上册
    │   │   └── 写字表.json
    │   └── 下册
    │       └── 写字表.json
    ├── 三年级
    │   ├── 上册
    │   │   ├── 写字表.json
    │   │   └── 词语表.json
    │   └── 下册
    │       ├── 写字表.json
    │       └── 词语表.json
# ....

数据库结构

CREATE TABLE IF NOT EXISTS units (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    lang TEXT NOT NULL,                    -- Language (e.g., 'zh', 'en')
    book TEXT NOT NULL,                    -- Book name (e.g., '语文(统编版)', 'join-in')
    grade TEXT NOT NULL,                   -- School grade level (e.g., '一年级', '二年级')
    term TEXT NOT NULL,                    -- Academic term (e.g., '上册', '下册')
    type TEXT,                             -- Type of content (e.g., '词语表', '生字表')
    unit TEXT NOT NULL,                    -- Unit identifier (e.g., '课文 1', '课文 2')
    UNIQUE(lang, book, grade, term, type, unit)  -- Ensure no duplicate units
);

CREATE TABLE IF NOT EXISTS words (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    unit_id INTEGER NOT NULL,              -- References units.id
    text TEXT NOT NULL,                    -- characters (e.g., '看见', '孩子', 'cinema')
    pinyin TEXT,                           -- Pinyin pronunciation (e.g., 'kàn jiàn', 'hái zǐ')
    pinyin_num TEXT,                       -- Numeric tone notation (e.g., 'kan3 jian4', 'hai2 zi3')
    explanation TEXT,                      -- Chinese explanation (e.g., '看见', '孩子', '电影院')
    level TEXT,                           -- Level of difficulty (e.g., 'core', 'regular', 'over')
    FOREIGN KEY (unit_id) REFERENCES units(id)
);

编写脚本生成 Sqlite 数据库

node vocabulary/index.mjs
 选择要处理的文件 (Ctrl+C 退出):
    [zh] 语文(统编版)/一年级/上册/写字表
    [zh] 语文(统编版)/一年级/下册/写字表
    # ...
    [en] join in 三年级起点/五年级/下册
    [en] join in 三年级起点/六年级/上册
    [en] join in 三年级起点/六年级/下册
# ⏎
 [zh] 语文(统编版)/一年级/上册/写字表	 Inserted data
 [zh] 语文(统编版)/一年级/下册/写字表	 Inserted data
 [zh] 语文(统编版)/二年级/上册/写字表	 Inserted data
# ...

番茄时钟

设计

  1. 任务列表和执行:
    • 任务按顺序排列,一个接一个执行
    • 整个任务列表有统一的开始、暂停、继续功能
    • 当前执行的任务会自动计时
  2. 任务管理:
    • 用户可以添加新任务,包括任务名称和预估时间
    • 用户可以编辑现有任务的名称和预估时间
    • 任务可以提前完成或延长时间
    • 完成的任务从列表中移除
  3. 时间管理:
    • 每个任务有预估完成时间(默认30分钟)
    • 实际时间可以与预估时间不同
    • 番茄工作法计时器(45分钟工作,15分钟休息)
  4. 界面设计:
    • 主界面显示有序任务列表
    • 当前执行任务高亮显示
    • 显示番茄计时器
    • 支持暗黑模式
  5. 数据记录和显示:
    • 任务完成后显示记录(可能包括实际用时、是否按时完成等)
    • 显示当日完成的番茄数量

用户流程

  1. 用户打开应用,看到任务列表和番茄计时器
  2. 用户可以添加新任务,设置任务名称和预估时间
  3. 用户可以调整任务顺序(如果需要的话)
  4. 用户点击”开始”按钮,第一个任务开始计时
  5. 任务进行中,用户可以:
    • 暂停整个任务列表
    • 提前完成当前任务
    • 延长当前任务时间
  6. 当前任务完成后,自动开始下一个任务
  7. 所有任务完成后,显示总结信息

总览图

graph TD
A[用户打开应用] --> B[查看任务列表和番茄计时器]
B --> C{用户操作}
C -->|添加新任务| D[设置任务名称和预估时间]
C -->|调整任务顺序| E[重新排列任务]
C -->|开始任务| F[点开始按钮]
F --> G{计时阶段}
G -->|放弃| B[返回任务列表]
G -->|完成| H[任务完成]

计时阶段

graph TD
F[点开始按钮] --> G[第一个任务开始计时]
G --> H{任务进行中}
H -->|暂停| I[暂停整个任务列表]
H -->|提前完成| J[结束当前任务]
H -->|任务完成| L{是否还有下一个任务?}
L -->|是| M[开始下一个任务]
M --> H
L -->|否| N[显示总结信息]
I --> H
J --> L

完成进度

P0: 核心功能(必须实现,构成 MVP - 最小可行产品)

  1. 任务列表的创建和显示
  2. 添加新任务(包括设置预估时间)
  3. 开始/暂停整个任务列表
  4. 任务自动按顺序执行
  5. 当前任务的计时功能
  6. 基本的番茄工作法计时器(45分钟工作,15分钟休息)

P1: 重要功能(显著提升用户体验,但不是 MVP 必需)

  1. 编辑现有任务(名称和预估时间)
  2. 提前完成或延长当前任务时间
  3. 任务完成后显示简单记录(如实际用时)
  4. 界面改进 MidJourney
  5. 不同阶段的动画效果 Rive

P2: 额外功能(优化和改进,可在后期版本中添加)

  1. 调整任务顺序
  2. 暗黑模式支持
  3. 数据可视化报告,持久化

字典

可选开源数据源

  1. 新华词典,爬虫的 https://github.com/pwxcoo/chinese-xinhua
  2. 爬虫的,数据结构更全 https://github.com/mapull/chinese-dictionary

最终采用了 mapull 的版本, 但是还需要进行下数据清洗

  1. 小学生场景仅需要 《通用规范汉字表》足够
  2. 拼音特殊符号,有些看上去一样,但是编码不一样
  3. 有部分标注错误

和听写汉字 一样,对于声调,需要输出成 sheng1 diao4 这种带声调数字的拼音。会需要用到 pinyin-pro 库。

结合 AI 和手工,准备一些元数据

const pinyinCombinations = { 
    a: ["a", "ai", "an", "ang", "ao"],
    b: ["ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi", "bian", "biao", "bie", "bin", "bing", "bo", "bu"],
    c: ["ca", "cai", "can", "cang", "cao", "ce", "cen", "ceng", "cha", "chai", "chan", "chang", "chao", "che", "chen", "cheng", "chi", "chong", "chou", "chu", "chua", "chuai", "chuan", "chuang", "chui", "chun", "chuo", "ci", "cong", "cou", "cu", "cuan", "cui", "cun", "cuo"],
    d: ["da", "dai", "dan", "dang", "dao", "de", "dei", "den", "deng", "di", "dian", "diao", "die", "ding", "diu", "dong", "dou", "du", "duan", "dui", "dun", "duo"],
    e: ["e", "ei", "en", "er"],
    f: ["fa", "fan", "fang", "fei", "fen", "feng", "fo", "fou", "fu"],
    g: ["ga", "gai", "gan", "gang", "gao", "ge", "gei", "gen", "geng", "gong", "gou", "gu", "gua", "guai", "guan", "guang", "gui", "gun", "guo"],
    h: ["ha", "hai", "han", "hang", "hao", "he", "hei", "hen", "heng", "hong", "hou", "hu", "hua", "huai", "huan", "huang", "hui", "hun", "huo"],
    j: ["ji", "jia", "jian", "jiang", "jiao", "jie", "jin", "jing", "jiong", "jiu", "ju", "juan", "jue", "jun"],
    k: ["ka", "kai", "kan", "kang", "kao", "ke", "ken", "keng", "kong", "kou", "ku", "kua", "kuai", "kuan", "kuang", "kui", "kun", "kuo"],
    l: ["la", "lai", "lan", "lang", "lao", "le", "lei", "leng", "li", "lia", "lian", "liang", "liao", "lie", "lin", "ling", "liu", "long", "lou", "lu", "luan", "lüe", "lun", "luo", "lü"],
    m: ["ma", "mai", "man", "mang", "mao", "me", "mei", "men", "meng", "mi", "mian", "miao", "mie", "min", "ming", "miu", "mo", "mou", "mu"],
    n: ["na", "nai", "nan", "nang", "nao", "ne", "nei", "nen", "neng", "ni", "nian", "niang", "niao", "nie", "nin", "ning", "niu", "nong", "nou", "nu", "nuan", "nüe", "nuo", "nü"],
    o: ["o", "ou"],
    p: ["pa", "pai", "pan", "pang", "pao", "pei", "pen", "peng", "pi", "pian", "piao", "pie", "pin", "ping", "po", "pou", "pu"],
    q: ["qi", "qia", "qian", "qiang", "qiao", "qie", "qin", "qing", "qiong", "qiu", "qu", "quan", "que", "qun"],
    r: ["ran", "rang", "rao", "re", "ren", "reng", "ri", "rong", "rou", "ru", "ruan", "rui", "run", "ruo"],
    s: ["sa", "sai", "san", "sang", "sao", "se", "sen", "seng", "sha", "shai", "shan", "shang", "shao", "she", "shei", "shen", "sheng", "shi", "shou", "shu", "shua", "shuai", "shuan", "shuang", "shui", "shun", "shuo", "si", "song", "sou", "su", "suan", "sui", "sun", "suo"],
    t: ["ta", "tai", "tan", "tang", "tao", "te", "teng", "ti", "tian", "tiao", "tie", "ting", "tong", "tou", "tu", "tuan", "tui", "tun", "tuo"],
    w: ["wa", "wai", "wan", "wang", "wei", "wen", "weng", "wo", "wu"],
    x: ["xi", "xia", "xian", "xiang", "xiao", "xie", "xin", "xing", "xiong", "xiu", "xu", "xuan", "xue", "xun"],
    y: ["ya", "yan", "yang", "yao", "ye", "yi", "yin", "ying", "yo", "yong", "you", "yu", "yuan", "yue", "yun"],
    z: ["za", "zai", "zan", "zang", "zao", "ze", "zei", "zen", "zeng", "zha", "zhai", "zhan", "zhang", "zhao", "zhe", "zhei", "zhen", "zheng", "zhi", "zhong", "zhou", "zhu", "zhua", "zhuai", "zhuan", "zhuang", "zhui", "zhun", "zhuo", "zi", "zong", "zou", "zu", "zuan", "zui", "zun", "zuo"]
}

// 部首列表参考来源 Wiki
// 顺序和变体组织,主要参考 《新华字典》
const radicalsByStroke = {
    1: ["一", "丨", "丶", "丿", "乛"],
    2: [
        "二", "十", "厂", "匚", "刂", "卜", "冂", "亻", "八", "人",
        "入", "⺈", "⺆", "勹", "𠘨", "儿", "匕", "几", "亠", "冫",
        "丷", "冖", "讠", "凵", "卩", "阝", "刀", "力", "又", "厶",
        "廴"
    ],
    3: [
        "干", "工", "土", "士", "扌", "艹", "寸", "廾", "大", "兀",
        "尢", "弋", "小", "⺌", "口", "囗", "山", "巾", "彳", "彡",
        "犭", "夕", "夂", "饣", "丬", "广", "门", "氵", "忄", "宀",
        "辶", "彐", "尸", "己", "弓", "子", "屮", "女", "飞", "马",
        "纟", "幺", "巛", "川", "彑"
    ],
    4: [
        "王", "无", "韦", "耂", "木", "攴", "支", "犬", "歹", "车",
        "牙", "戈", "旡", "比", "瓦", "止", "⺗", "日", "⺝", "贝",
        "水", "见", "牛", "手", "龵", "气", "毛", "攵", "长", "片",
        "斤", "爪", "父", "爫", "月", "氏", "欠", "风", "殳", "文", 
        "方", "火", "斗", "灬", "户", "礻", "心", "肀", "爿", "毋", 
        "卝", "厄", "爻"
    ],
    5: [
        "玉", "示", "甘", "石", "龙", "业", "氺", "目", "田", "罒",
        "皿", "钅", "生", "矢", "禾", "白", "瓜", "鸟", "疒", "立",
        "穴", "衤", "疋", "皮", "癶", "矛", "母", "用", 
    ],
    6: ["先", "竹", "米", "糸", "糹", "缶", "羊", "羽", "而", "耒", "耳", "聿", "肉", "臣", "自", "至", "臼", "舌", "舟", "艮", "色", "虍", "虫", "血", "行", "衣", "覀", "页", "齐"],
    7: ["克", "卤", "角", "言", "谷", "豆", "豕", "豸", "貝", "赤", "走", "足", "身", "辛", "辰", "邑", "酉", "采", "里", "麦"],
    8: ["金", "長", "阜", "隶", "隹", "雨", "靑", "青", "非", "靣", "鱼", "齿"],
    // nine and above
    9: ["面", "革",  "韭", "音", "首", "香", "骨", "鬼", "高", "髟", "鬥", "鬯", "鬲", "魚", "鹿", "麻", "黄", "黍", "黑", "黹", "鼎", "鼓", "鼠", "鼻", "龠"]
}

/** the radical display name: "$mainForm ($variants)" */
const radicalVariants = {
    "乛": ["亅", "乚", "乙"],
    "阝": ["左耳", "右耳"],
    "己": ["已", "巳"],
    "卩": ["㔾"],
    "王": ["𤣩"],
    "日": ["曰", "⺜"],
    "牛": ["牜"],
    "疋": ["𤴔"],
    "覀": ["西"],
    "竹": ["𥫗"],
    "羊": ["⺶", "𦍌"],
    "聿": ["⺻"],
    "足": ["𧾷"],
    "雨": ["⻗"],
    "黾": ["黽"],
    "食": ["飠"]
}

数据结构和脚本,不再赘述。

休息环节

学习间隙的短暂休息时间(约15分钟)提供有趣且有益的活动建议,帮助他们放松身心,为下一个学习周期做好准备。

活动类别

  • 学习效率提升
    • 时间管理技巧
    • 注意力集中练习
    • 记忆力提升方法
  • 身心健康
    • 简单的伸展运动
    • 冥想和呼吸练习
    • 积极思维培养
  • 生活技能
    • 整理和收纳方法
    • 基础家务技能
    • 个人卫生习惯

休息铃声

放一点点 🤏 古典音乐,放松心情。

./Resources/classic/
├── Air on the G String.mp3
├── Claire de Lune.mp3
├── June Barcarolle.mp3
└── Serenade in G Major.mp3