【小程序】考研英语词汇 Flashcard — 详细设计

本项目站内源代码下载地址

技术栈:Next.js 16 + React 19 + TypeScript + Tailwind CSS v4 + shadcn/ui + Zustand + Framer Motion

目标平台:Web(PWA/移动端优先)


1. 项目概述

1.1 项目定位

本项目是一款面向考研(研究生入学考试)英语备考的词汇闪卡学习工具,采用移动端优先的交互设计,支持:

  • 闪卡记忆:3D翻转卡片展示单词、音标、释义、真题例句与记忆锚点
  • 单词列表:分类浏览、搜索、收藏、掌握/熟悉标记
  • 测验模式:四选一选择题,自动从同分类中生成干扰项
  • 学习统计:今日进度、总体掌握率、分类进度、每日目标设定

1.2 核心特性

特性 说明
词汇覆盖 约 5500+ 考研大纲词汇,分核心词、阅读高频、完形高频、写作加分、基础词五大类
多分类标签 每个单词可属于多个分类(如核心词同时标记为阅读/写作)
数据去重 14 个数据源按优先级合并,保留最详细的词条信息
本地持久化 学习进度、收藏、测验成绩通过 localStorage 持久化
每日目标 支持 20/30/50/80/100 词每日学习目标,自动跨天重置
交互动画 卡片翻转、页面切换、进度条动画均采用 Framer Motion

2. 系统架构

2.1 整体架构图

#mermaid-svg-QV430reJVRVR5ZrW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QV430reJVRVR5ZrW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QV430reJVRVR5ZrW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QV430reJVRVR5ZrW .error-icon{fill:#552222;}#mermaid-svg-QV430reJVRVR5ZrW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QV430reJVRVR5ZrW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QV430reJVRVR5ZrW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QV430reJVRVR5ZrW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QV430reJVRVR5ZrW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QV430reJVRVR5ZrW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QV430reJVRVR5ZrW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QV430reJVRVR5ZrW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QV430reJVRVR5ZrW .marker.cross{stroke:#333333;}#mermaid-svg-QV430reJVRVR5ZrW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QV430reJVRVR5ZrW p{margin:0;}#mermaid-svg-QV430reJVRVR5ZrW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QV430reJVRVR5ZrW .cluster-label text{fill:#333;}#mermaid-svg-QV430reJVRVR5ZrW .cluster-label span{color:#333;}#mermaid-svg-QV430reJVRVR5ZrW .cluster-label span p{background-color:transparent;}#mermaid-svg-QV430reJVRVR5ZrW .label text,#mermaid-svg-QV430reJVRVR5ZrW span{fill:#333;color:#333;}#mermaid-svg-QV430reJVRVR5ZrW .node rect,#mermaid-svg-QV430reJVRVR5ZrW .node circle,#mermaid-svg-QV430reJVRVR5ZrW .node ellipse,#mermaid-svg-QV430reJVRVR5ZrW .node polygon,#mermaid-svg-QV430reJVRVR5ZrW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QV430reJVRVR5ZrW .rough-node .label text,#mermaid-svg-QV430reJVRVR5ZrW .node .label text,#mermaid-svg-QV430reJVRVR5ZrW .image-shape .label,#mermaid-svg-QV430reJVRVR5ZrW .icon-shape .label{text-anchor:middle;}#mermaid-svg-QV430reJVRVR5ZrW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QV430reJVRVR5ZrW .rough-node .label,#mermaid-svg-QV430reJVRVR5ZrW .node .label,#mermaid-svg-QV430reJVRVR5ZrW .image-shape .label,#mermaid-svg-QV430reJVRVR5ZrW .icon-shape .label{text-align:center;}#mermaid-svg-QV430reJVRVR5ZrW .node.clickable{cursor:pointer;}#mermaid-svg-QV430reJVRVR5ZrW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QV430reJVRVR5ZrW .arrowheadPath{fill:#333333;}#mermaid-svg-QV430reJVRVR5ZrW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QV430reJVRVR5ZrW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QV430reJVRVR5ZrW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QV430reJVRVR5ZrW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QV430reJVRVR5ZrW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QV430reJVRVR5ZrW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QV430reJVRVR5ZrW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QV430reJVRVR5ZrW .cluster text{fill:#333;}#mermaid-svg-QV430reJVRVR5ZrW .cluster span{color:#333;}#mermaid-svg-QV430reJVRVR5ZrW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QV430reJVRVR5ZrW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QV430reJVRVR5ZrW rect.text{fill:none;stroke-width:0;}#mermaid-svg-QV430reJVRVR5ZrW .icon-shape,#mermaid-svg-QV430reJVRVR5ZrW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QV430reJVRVR5ZrW .icon-shape p,#mermaid-svg-QV430reJVRVR5ZrW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QV430reJVRVR5ZrW .icon-shape .label rect,#mermaid-svg-QV430reJVRVR5ZrW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QV430reJVRVR5ZrW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QV430reJVRVR5ZrW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QV430reJVRVR5ZrW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 外部依赖
客户端 (Next.js App Router)
persist
UI 层

src/app/page.tsx
组件层

src/components/ui/*
状态管理层

Zustand + persist
数据层

src/data/*
Hooks 层

src/hooks/*
Tailwind CSS v4
Framer Motion
Lucide Icons
shadcn/ui
localStorage

2.2 技术栈明细

层级 技术选型 版本 用途
框架 Next.js 16.1.1 React 全栈框架,App Router
运行时 React 19.0.0 UI 库
语言 TypeScript 5.x 类型安全
样式 Tailwind CSS 4.x 原子化 CSS
UI 组件 shadcn/ui latest Radix UI 封装组件库
状态管理 Zustand 5.0.6 轻量级全局状态
动画 Framer Motion 12.23.2 交互动画
图标 Lucide React 0.525.0 矢量图标
构建 Bun 1.3.4 包管理与运行时
ORM Prisma 6.11.1 数据库模型(当前未深度使用)
数据库 SQLite - 本地数据库(当前未深度使用)

3. 目录结构

复制代码
考研词汇练习/
├── src/
│   ├── app/
│   │   ├── api/route.ts          # API 路由(占位)
│   │   ├── globals.css           # Tailwind 主题与 CSS 变量
│   │   ├── layout.tsx            # 根布局(字体、Metadata)
│   │   └── page.tsx              # 主页面(单页应用,含所有 Tab)
│   ├── components/ui/            # shadcn/ui 组件(~50 个)
│   │   ├── button.tsx
│   │   ├── card.tsx
│   │   ├── input.tsx
│   │   ├── progress.tsx
│   │   ├── badge.tsx
│   │   ├── scroll-area.tsx
│   │   ├── separator.tsx
│   │   └── ...
│   ├── data/                     # 词汇数据源(14 个文件)
│   │   ├── vocabulary.ts         # 核心词汇(最详细,40+ 词,含例句)
│   │   ├── vocab-core-ae.ts      # 核心词 A-E
│   │   ├── vocab-core-fn.ts      # 核心词 F-N
│   │   ├── vocab-core-oz.ts      # 核心词 O-Z
│   │   ├── vocab-core-expanded.ts
│   │   ├── vocab-ac.ts           # A-C 补充词
│   │   ├── vocab-dh.ts           # D-H 补充词
│   │   ├── vocab-io.ts           # I-O 补充词
│   │   ├── vocab-ps.ts           # P-S 补充词
│   │   ├── vocab-tz.ts           # T-Z 补充词
│   │   ├── vocab-extra.ts
│   │   ├── vocab-supplement-al.ts
│   │   ├── vocab-supplement-mz.ts
│   │   ├── vocab-rcw.ts
│   │   ├── vocab-final-supplement.ts
│   │   └── index.ts              # 数据聚合与去重逻辑
│   ├── store/
│   │   └── vocab-store.ts        # Zustand 全局状态
│   └── hooks/
│       ├── use-mobile.ts         # 移动端检测
│       └── use-toast.ts          # Toast 通知
├── prisma/
│   └── schema.prisma             # 数据库模型(User, Post)
├── public/
│   ├── logo.svg
│   └── robots.txt
├── scripts/
│   └── gen-vocab.js              # 词汇生成脚本
├── .zscripts/                    # 自定义脚本(build/dev/start)
├── next.config.ts                # Next.js 配置(standalone 输出)
├── components.json               # shadcn/ui 配置
├── package.json
├── bun.lock
└── Caddyfile                     # Caddy 反向代理配置

4. 数据模型设计

4.1 词汇数据模型

#mermaid-svg-swoNr5wlslxHdgyp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-swoNr5wlslxHdgyp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-swoNr5wlslxHdgyp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-swoNr5wlslxHdgyp .error-icon{fill:#552222;}#mermaid-svg-swoNr5wlslxHdgyp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-swoNr5wlslxHdgyp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-swoNr5wlslxHdgyp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-swoNr5wlslxHdgyp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-swoNr5wlslxHdgyp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-swoNr5wlslxHdgyp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-swoNr5wlslxHdgyp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-swoNr5wlslxHdgyp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-swoNr5wlslxHdgyp .marker.cross{stroke:#333333;}#mermaid-svg-swoNr5wlslxHdgyp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-swoNr5wlslxHdgyp p{margin:0;}#mermaid-svg-swoNr5wlslxHdgyp g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-swoNr5wlslxHdgyp g.classGroup text .title{font-weight:bolder;}#mermaid-svg-swoNr5wlslxHdgyp .cluster-label text{fill:#333;}#mermaid-svg-swoNr5wlslxHdgyp .cluster-label span{color:#333;}#mermaid-svg-swoNr5wlslxHdgyp .cluster-label span p{background-color:transparent;}#mermaid-svg-swoNr5wlslxHdgyp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-swoNr5wlslxHdgyp .cluster text{fill:#333;}#mermaid-svg-swoNr5wlslxHdgyp .cluster span{color:#333;}#mermaid-svg-swoNr5wlslxHdgyp .nodeLabel,#mermaid-svg-swoNr5wlslxHdgyp .edgeLabel{color:#131300;}#mermaid-svg-swoNr5wlslxHdgyp .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-swoNr5wlslxHdgyp .label text{fill:#131300;}#mermaid-svg-swoNr5wlslxHdgyp .labelBkg{background:#ECECFF;}#mermaid-svg-swoNr5wlslxHdgyp .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-swoNr5wlslxHdgyp .classTitle{font-weight:bolder;}#mermaid-svg-swoNr5wlslxHdgyp .node rect,#mermaid-svg-swoNr5wlslxHdgyp .node circle,#mermaid-svg-swoNr5wlslxHdgyp .node ellipse,#mermaid-svg-swoNr5wlslxHdgyp .node polygon,#mermaid-svg-swoNr5wlslxHdgyp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-swoNr5wlslxHdgyp .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp g.clickable{cursor:pointer;}#mermaid-svg-swoNr5wlslxHdgyp g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-swoNr5wlslxHdgyp g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-swoNr5wlslxHdgyp .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-swoNr5wlslxHdgyp .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-swoNr5wlslxHdgyp .dashed-line{stroke-dasharray:3;}#mermaid-svg-swoNr5wlslxHdgyp .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-swoNr5wlslxHdgyp #compositionStart,#mermaid-svg-swoNr5wlslxHdgyp .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #compositionEnd,#mermaid-svg-swoNr5wlslxHdgyp .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #dependencyStart,#mermaid-svg-swoNr5wlslxHdgyp .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #dependencyStart,#mermaid-svg-swoNr5wlslxHdgyp .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #extensionStart,#mermaid-svg-swoNr5wlslxHdgyp .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #extensionEnd,#mermaid-svg-swoNr5wlslxHdgyp .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #aggregationStart,#mermaid-svg-swoNr5wlslxHdgyp .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #aggregationEnd,#mermaid-svg-swoNr5wlslxHdgyp .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #lollipopStart,#mermaid-svg-swoNr5wlslxHdgyp .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp #lollipopEnd,#mermaid-svg-swoNr5wlslxHdgyp .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-swoNr5wlslxHdgyp .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-swoNr5wlslxHdgyp .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-swoNr5wlslxHdgyp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-swoNr5wlslxHdgyp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-swoNr5wlslxHdgyp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} belongs to
VocabWord
+string id
+string word
+string phonetic
+string coreMeaning
+string exampleEn
+string exampleCn
+string memoryTip
+string category
+string\[\] categories
+string\[\] tags
+number frequency
+number mastery
Category
+string key
+string label
+Icon icon
+string color

4.2 词汇字段说明

字段 类型 说明
id string 唯一标识,格式 w{序号}
word string 英文单词
phonetic string 音标(IPA)
coreMeaning string 核心中文释义
exampleEn string 真题例句(英文)
exampleCn string 真题例句(中文翻译)
memoryTip string 记忆提示/锚点
category enum 主分类:core/reading/cloze/writing/basic
categories string[] 自动分配的多个分类标签
tags string[] 词性标签:动词/名词/形容词/高频/搭配
frequency number 考频等级 1-5
mastery number 掌握等级 0-2(当前未使用)

4.3 状态管理模型(Zustand Store)

#mermaid-svg-bEWBnsvqiYGttaQF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bEWBnsvqiYGttaQF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bEWBnsvqiYGttaQF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bEWBnsvqiYGttaQF .error-icon{fill:#552222;}#mermaid-svg-bEWBnsvqiYGttaQF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bEWBnsvqiYGttaQF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bEWBnsvqiYGttaQF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bEWBnsvqiYGttaQF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bEWBnsvqiYGttaQF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bEWBnsvqiYGttaQF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bEWBnsvqiYGttaQF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bEWBnsvqiYGttaQF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bEWBnsvqiYGttaQF .marker.cross{stroke:#333333;}#mermaid-svg-bEWBnsvqiYGttaQF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bEWBnsvqiYGttaQF p{margin:0;}#mermaid-svg-bEWBnsvqiYGttaQF g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-bEWBnsvqiYGttaQF g.classGroup text .title{font-weight:bolder;}#mermaid-svg-bEWBnsvqiYGttaQF .cluster-label text{fill:#333;}#mermaid-svg-bEWBnsvqiYGttaQF .cluster-label span{color:#333;}#mermaid-svg-bEWBnsvqiYGttaQF .cluster-label span p{background-color:transparent;}#mermaid-svg-bEWBnsvqiYGttaQF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bEWBnsvqiYGttaQF .cluster text{fill:#333;}#mermaid-svg-bEWBnsvqiYGttaQF .cluster span{color:#333;}#mermaid-svg-bEWBnsvqiYGttaQF .nodeLabel,#mermaid-svg-bEWBnsvqiYGttaQF .edgeLabel{color:#131300;}#mermaid-svg-bEWBnsvqiYGttaQF .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-bEWBnsvqiYGttaQF .label text{fill:#131300;}#mermaid-svg-bEWBnsvqiYGttaQF .labelBkg{background:#ECECFF;}#mermaid-svg-bEWBnsvqiYGttaQF .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-bEWBnsvqiYGttaQF .classTitle{font-weight:bolder;}#mermaid-svg-bEWBnsvqiYGttaQF .node rect,#mermaid-svg-bEWBnsvqiYGttaQF .node circle,#mermaid-svg-bEWBnsvqiYGttaQF .node ellipse,#mermaid-svg-bEWBnsvqiYGttaQF .node polygon,#mermaid-svg-bEWBnsvqiYGttaQF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bEWBnsvqiYGttaQF .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF g.clickable{cursor:pointer;}#mermaid-svg-bEWBnsvqiYGttaQF g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-bEWBnsvqiYGttaQF g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-bEWBnsvqiYGttaQF .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-bEWBnsvqiYGttaQF .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-bEWBnsvqiYGttaQF .dashed-line{stroke-dasharray:3;}#mermaid-svg-bEWBnsvqiYGttaQF .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-bEWBnsvqiYGttaQF #compositionStart,#mermaid-svg-bEWBnsvqiYGttaQF .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #compositionEnd,#mermaid-svg-bEWBnsvqiYGttaQF .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #dependencyStart,#mermaid-svg-bEWBnsvqiYGttaQF .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #dependencyStart,#mermaid-svg-bEWBnsvqiYGttaQF .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #extensionStart,#mermaid-svg-bEWBnsvqiYGttaQF .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #extensionEnd,#mermaid-svg-bEWBnsvqiYGttaQF .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #aggregationStart,#mermaid-svg-bEWBnsvqiYGttaQF .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #aggregationEnd,#mermaid-svg-bEWBnsvqiYGttaQF .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #lollipopStart,#mermaid-svg-bEWBnsvqiYGttaQF .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF #lollipopEnd,#mermaid-svg-bEWBnsvqiYGttaQF .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-bEWBnsvqiYGttaQF .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-bEWBnsvqiYGttaQF .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bEWBnsvqiYGttaQF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bEWBnsvqiYGttaQF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bEWBnsvqiYGttaQF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} VocabStore
+string currentCategory
+number currentWordIndex
+boolean isFlipped
+string\[\] masteredWords
+string\[\] familiarWords
+string\[\] bookmarkedWords
+number quizScore
+number quizTotal
+number quizCurrentIndex
+boolean quizAnswered
+number quizSelectedAnswer
+string searchQuery
+string learningMode
+number dailyGoal
+number dailyLearned
+string dailyDate
+setCategory(category)
+nextWord()
+prevWord()
+flipCard()
+markMastered(wordId)
+markFamiliar(wordId)
+toggleBookmark(wordId)
+submitQuizAnswer(selected, correct)
+incrementDailyLearned()
+getStats()

4.4 数据持久化流程

localStorage persist 中间件 Zustand Store 页面组件 用户 localStorage persist 中间件 Zustand Store 页面组件 用户 #mermaid-svg-0RljfSSnVTRx9GVZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0RljfSSnVTRx9GVZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0RljfSSnVTRx9GVZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0RljfSSnVTRx9GVZ .error-icon{fill:#552222;}#mermaid-svg-0RljfSSnVTRx9GVZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0RljfSSnVTRx9GVZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0RljfSSnVTRx9GVZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0RljfSSnVTRx9GVZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0RljfSSnVTRx9GVZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0RljfSSnVTRx9GVZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0RljfSSnVTRx9GVZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0RljfSSnVTRx9GVZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0RljfSSnVTRx9GVZ .marker.cross{stroke:#333333;}#mermaid-svg-0RljfSSnVTRx9GVZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0RljfSSnVTRx9GVZ p{margin:0;}#mermaid-svg-0RljfSSnVTRx9GVZ .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-0RljfSSnVTRx9GVZ text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-0RljfSSnVTRx9GVZ .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-0RljfSSnVTRx9GVZ .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-0RljfSSnVTRx9GVZ .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-0RljfSSnVTRx9GVZ .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-0RljfSSnVTRx9GVZ #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-0RljfSSnVTRx9GVZ .sequenceNumber{fill:white;}#mermaid-svg-0RljfSSnVTRx9GVZ #sequencenumber{fill:#333;}#mermaid-svg-0RljfSSnVTRx9GVZ #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-0RljfSSnVTRx9GVZ .messageText{fill:#333;stroke:none;}#mermaid-svg-0RljfSSnVTRx9GVZ .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-0RljfSSnVTRx9GVZ .labelText,#mermaid-svg-0RljfSSnVTRx9GVZ .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-0RljfSSnVTRx9GVZ .loopText,#mermaid-svg-0RljfSSnVTRx9GVZ .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-0RljfSSnVTRx9GVZ .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-0RljfSSnVTRx9GVZ .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-0RljfSSnVTRx9GVZ .noteText,#mermaid-svg-0RljfSSnVTRx9GVZ .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-0RljfSSnVTRx9GVZ .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-0RljfSSnVTRx9GVZ .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-0RljfSSnVTRx9GVZ .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-0RljfSSnVTRx9GVZ .actorPopupMenu{position:absolute;}#mermaid-svg-0RljfSSnVTRx9GVZ .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-0RljfSSnVTRx9GVZ .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-0RljfSSnVTRx9GVZ .actor-man circle,#mermaid-svg-0RljfSSnVTRx9GVZ line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-0RljfSSnVTRx9GVZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 标记单词为"已掌握" markMastered(wordId) 更新 masteredWords 数组 状态变更触发持久化 序列化并写入 vocab-store 确认存储 完成 状态更新,UI 重渲染


5. 页面与组件设计

5.1 页面结构

本项目采用**单页应用(SPA)**模式,所有功能集中在 page.tsx 中,通过底部 Tab Bar 切换视图。
#mermaid-svg-8DPZGMHkQUmEZ5e9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .error-icon{fill:#552222;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .marker.cross{stroke:#333333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8DPZGMHkQUmEZ5e9 p{margin:0;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .cluster-label text{fill:#333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .cluster-label span{color:#333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .cluster-label span p{background-color:transparent;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .label text,#mermaid-svg-8DPZGMHkQUmEZ5e9 span{fill:#333;color:#333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .node rect,#mermaid-svg-8DPZGMHkQUmEZ5e9 .node circle,#mermaid-svg-8DPZGMHkQUmEZ5e9 .node ellipse,#mermaid-svg-8DPZGMHkQUmEZ5e9 .node polygon,#mermaid-svg-8DPZGMHkQUmEZ5e9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .rough-node .label text,#mermaid-svg-8DPZGMHkQUmEZ5e9 .node .label text,#mermaid-svg-8DPZGMHkQUmEZ5e9 .image-shape .label,#mermaid-svg-8DPZGMHkQUmEZ5e9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .rough-node .label,#mermaid-svg-8DPZGMHkQUmEZ5e9 .node .label,#mermaid-svg-8DPZGMHkQUmEZ5e9 .image-shape .label,#mermaid-svg-8DPZGMHkQUmEZ5e9 .icon-shape .label{text-align:center;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .node.clickable{cursor:pointer;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .arrowheadPath{fill:#333333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8DPZGMHkQUmEZ5e9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8DPZGMHkQUmEZ5e9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8DPZGMHkQUmEZ5e9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .cluster text{fill:#333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .cluster span{color:#333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8DPZGMHkQUmEZ5e9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .icon-shape,#mermaid-svg-8DPZGMHkQUmEZ5e9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .icon-shape p,#mermaid-svg-8DPZGMHkQUmEZ5e9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .icon-shape .label rect,#mermaid-svg-8DPZGMHkQUmEZ5e9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8DPZGMHkQUmEZ5e9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8DPZGMHkQUmEZ5e9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8DPZGMHkQUmEZ5e9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} VocabApp (page.tsx)
单词子模式
Tab 内容区
FlashcardTab

闪卡模式
底部导航栏

TabBar
HomeTab

首页
WordsTab

单词
QuizMode

测验
ProfileTab

我的
WordListTab

列表模式

5.2 底部导航栏

Tab 图标 标签 功能
home Home 首页 学习概览、今日推荐、分类入口
words BookOpen 单词 闪卡/列表模式切换
quiz Brain 测验 四选一选择题测验
profile User 我的 学习统计、进度、设置

5.3 首页(HomeTab)

#mermaid-svg-14fuhXDnBjGvv8Qn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-14fuhXDnBjGvv8Qn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-14fuhXDnBjGvv8Qn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-14fuhXDnBjGvv8Qn .error-icon{fill:#552222;}#mermaid-svg-14fuhXDnBjGvv8Qn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-14fuhXDnBjGvv8Qn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-14fuhXDnBjGvv8Qn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-14fuhXDnBjGvv8Qn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-14fuhXDnBjGvv8Qn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-14fuhXDnBjGvv8Qn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-14fuhXDnBjGvv8Qn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-14fuhXDnBjGvv8Qn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-14fuhXDnBjGvv8Qn .marker.cross{stroke:#333333;}#mermaid-svg-14fuhXDnBjGvv8Qn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-14fuhXDnBjGvv8Qn p{margin:0;}#mermaid-svg-14fuhXDnBjGvv8Qn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-14fuhXDnBjGvv8Qn .cluster-label text{fill:#333;}#mermaid-svg-14fuhXDnBjGvv8Qn .cluster-label span{color:#333;}#mermaid-svg-14fuhXDnBjGvv8Qn .cluster-label span p{background-color:transparent;}#mermaid-svg-14fuhXDnBjGvv8Qn .label text,#mermaid-svg-14fuhXDnBjGvv8Qn span{fill:#333;color:#333;}#mermaid-svg-14fuhXDnBjGvv8Qn .node rect,#mermaid-svg-14fuhXDnBjGvv8Qn .node circle,#mermaid-svg-14fuhXDnBjGvv8Qn .node ellipse,#mermaid-svg-14fuhXDnBjGvv8Qn .node polygon,#mermaid-svg-14fuhXDnBjGvv8Qn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-14fuhXDnBjGvv8Qn .rough-node .label text,#mermaid-svg-14fuhXDnBjGvv8Qn .node .label text,#mermaid-svg-14fuhXDnBjGvv8Qn .image-shape .label,#mermaid-svg-14fuhXDnBjGvv8Qn .icon-shape .label{text-anchor:middle;}#mermaid-svg-14fuhXDnBjGvv8Qn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-14fuhXDnBjGvv8Qn .rough-node .label,#mermaid-svg-14fuhXDnBjGvv8Qn .node .label,#mermaid-svg-14fuhXDnBjGvv8Qn .image-shape .label,#mermaid-svg-14fuhXDnBjGvv8Qn .icon-shape .label{text-align:center;}#mermaid-svg-14fuhXDnBjGvv8Qn .node.clickable{cursor:pointer;}#mermaid-svg-14fuhXDnBjGvv8Qn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-14fuhXDnBjGvv8Qn .arrowheadPath{fill:#333333;}#mermaid-svg-14fuhXDnBjGvv8Qn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-14fuhXDnBjGvv8Qn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-14fuhXDnBjGvv8Qn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-14fuhXDnBjGvv8Qn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-14fuhXDnBjGvv8Qn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-14fuhXDnBjGvv8Qn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-14fuhXDnBjGvv8Qn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-14fuhXDnBjGvv8Qn .cluster text{fill:#333;}#mermaid-svg-14fuhXDnBjGvv8Qn .cluster span{color:#333;}#mermaid-svg-14fuhXDnBjGvv8Qn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-14fuhXDnBjGvv8Qn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-14fuhXDnBjGvv8Qn rect.text{fill:none;stroke-width:0;}#mermaid-svg-14fuhXDnBjGvv8Qn .icon-shape,#mermaid-svg-14fuhXDnBjGvv8Qn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-14fuhXDnBjGvv8Qn .icon-shape p,#mermaid-svg-14fuhXDnBjGvv8Qn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-14fuhXDnBjGvv8Qn .icon-shape .label rect,#mermaid-svg-14fuhXDnBjGvv8Qn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-14fuhXDnBjGvv8Qn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-14fuhXDnBjGvv8Qn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-14fuhXDnBjGvv8Qn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} HomeTab
标题区

考研英语词汇 💪
今日进度卡片

渐变背景 + 动画进度条
统计网格

总词量/已掌握/熟悉/收藏
分类快捷入口

2x2 网格
今日推荐

随机 5 词 + 收藏按钮

核心交互:

  • 点击分类卡片 → 切换到单词 Tab 并进入闪卡模式
  • 点击收藏按钮 → 切换单词收藏状态
  • 进度条动画 → Framer Motion animate={``{ width }}

5.4 闪卡模式(FlashcardTab)

#mermaid-svg-kkk2fnWp8kLWsG9b{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kkk2fnWp8kLWsG9b .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kkk2fnWp8kLWsG9b .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kkk2fnWp8kLWsG9b .error-icon{fill:#552222;}#mermaid-svg-kkk2fnWp8kLWsG9b .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kkk2fnWp8kLWsG9b .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kkk2fnWp8kLWsG9b .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kkk2fnWp8kLWsG9b .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kkk2fnWp8kLWsG9b .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kkk2fnWp8kLWsG9b .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kkk2fnWp8kLWsG9b .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kkk2fnWp8kLWsG9b .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kkk2fnWp8kLWsG9b .marker.cross{stroke:#333333;}#mermaid-svg-kkk2fnWp8kLWsG9b svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kkk2fnWp8kLWsG9b p{margin:0;}#mermaid-svg-kkk2fnWp8kLWsG9b .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kkk2fnWp8kLWsG9b .cluster-label text{fill:#333;}#mermaid-svg-kkk2fnWp8kLWsG9b .cluster-label span{color:#333;}#mermaid-svg-kkk2fnWp8kLWsG9b .cluster-label span p{background-color:transparent;}#mermaid-svg-kkk2fnWp8kLWsG9b .label text,#mermaid-svg-kkk2fnWp8kLWsG9b span{fill:#333;color:#333;}#mermaid-svg-kkk2fnWp8kLWsG9b .node rect,#mermaid-svg-kkk2fnWp8kLWsG9b .node circle,#mermaid-svg-kkk2fnWp8kLWsG9b .node ellipse,#mermaid-svg-kkk2fnWp8kLWsG9b .node polygon,#mermaid-svg-kkk2fnWp8kLWsG9b .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kkk2fnWp8kLWsG9b .rough-node .label text,#mermaid-svg-kkk2fnWp8kLWsG9b .node .label text,#mermaid-svg-kkk2fnWp8kLWsG9b .image-shape .label,#mermaid-svg-kkk2fnWp8kLWsG9b .icon-shape .label{text-anchor:middle;}#mermaid-svg-kkk2fnWp8kLWsG9b .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kkk2fnWp8kLWsG9b .rough-node .label,#mermaid-svg-kkk2fnWp8kLWsG9b .node .label,#mermaid-svg-kkk2fnWp8kLWsG9b .image-shape .label,#mermaid-svg-kkk2fnWp8kLWsG9b .icon-shape .label{text-align:center;}#mermaid-svg-kkk2fnWp8kLWsG9b .node.clickable{cursor:pointer;}#mermaid-svg-kkk2fnWp8kLWsG9b .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kkk2fnWp8kLWsG9b .arrowheadPath{fill:#333333;}#mermaid-svg-kkk2fnWp8kLWsG9b .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kkk2fnWp8kLWsG9b .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kkk2fnWp8kLWsG9b .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kkk2fnWp8kLWsG9b .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kkk2fnWp8kLWsG9b .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kkk2fnWp8kLWsG9b .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kkk2fnWp8kLWsG9b .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kkk2fnWp8kLWsG9b .cluster text{fill:#333;}#mermaid-svg-kkk2fnWp8kLWsG9b .cluster span{color:#333;}#mermaid-svg-kkk2fnWp8kLWsG9b div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kkk2fnWp8kLWsG9b .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kkk2fnWp8kLWsG9b rect.text{fill:none;stroke-width:0;}#mermaid-svg-kkk2fnWp8kLWsG9b .icon-shape,#mermaid-svg-kkk2fnWp8kLWsG9b .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kkk2fnWp8kLWsG9b .icon-shape p,#mermaid-svg-kkk2fnWp8kLWsG9b .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kkk2fnWp8kLWsG9b .icon-shape .label rect,#mermaid-svg-kkk2fnWp8kLWsG9b .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kkk2fnWp8kLWsG9b .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kkk2fnWp8kLWsG9b .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kkk2fnWp8kLWsG9b :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} FlashcardTab
分类筛选栏
进度指示

Progress + 计数
卡片区域
控制区
FlashCard 组件

3D 翻转动画
正面

单词 + 音标 + 分类标签 + 考频
背面

释义 + 例句 + 记忆提示
掌握/熟悉 按钮
上一张 / 翻转 / 下一张

3D 翻转实现:
#mermaid-svg-yfSZRmoZndq77giy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yfSZRmoZndq77giy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yfSZRmoZndq77giy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yfSZRmoZndq77giy .error-icon{fill:#552222;}#mermaid-svg-yfSZRmoZndq77giy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yfSZRmoZndq77giy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yfSZRmoZndq77giy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yfSZRmoZndq77giy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yfSZRmoZndq77giy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yfSZRmoZndq77giy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yfSZRmoZndq77giy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yfSZRmoZndq77giy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yfSZRmoZndq77giy .marker.cross{stroke:#333333;}#mermaid-svg-yfSZRmoZndq77giy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yfSZRmoZndq77giy p{margin:0;}#mermaid-svg-yfSZRmoZndq77giy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yfSZRmoZndq77giy .cluster-label text{fill:#333;}#mermaid-svg-yfSZRmoZndq77giy .cluster-label span{color:#333;}#mermaid-svg-yfSZRmoZndq77giy .cluster-label span p{background-color:transparent;}#mermaid-svg-yfSZRmoZndq77giy .label text,#mermaid-svg-yfSZRmoZndq77giy span{fill:#333;color:#333;}#mermaid-svg-yfSZRmoZndq77giy .node rect,#mermaid-svg-yfSZRmoZndq77giy .node circle,#mermaid-svg-yfSZRmoZndq77giy .node ellipse,#mermaid-svg-yfSZRmoZndq77giy .node polygon,#mermaid-svg-yfSZRmoZndq77giy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yfSZRmoZndq77giy .rough-node .label text,#mermaid-svg-yfSZRmoZndq77giy .node .label text,#mermaid-svg-yfSZRmoZndq77giy .image-shape .label,#mermaid-svg-yfSZRmoZndq77giy .icon-shape .label{text-anchor:middle;}#mermaid-svg-yfSZRmoZndq77giy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yfSZRmoZndq77giy .rough-node .label,#mermaid-svg-yfSZRmoZndq77giy .node .label,#mermaid-svg-yfSZRmoZndq77giy .image-shape .label,#mermaid-svg-yfSZRmoZndq77giy .icon-shape .label{text-align:center;}#mermaid-svg-yfSZRmoZndq77giy .node.clickable{cursor:pointer;}#mermaid-svg-yfSZRmoZndq77giy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yfSZRmoZndq77giy .arrowheadPath{fill:#333333;}#mermaid-svg-yfSZRmoZndq77giy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yfSZRmoZndq77giy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yfSZRmoZndq77giy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yfSZRmoZndq77giy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yfSZRmoZndq77giy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yfSZRmoZndq77giy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yfSZRmoZndq77giy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yfSZRmoZndq77giy .cluster text{fill:#333;}#mermaid-svg-yfSZRmoZndq77giy .cluster span{color:#333;}#mermaid-svg-yfSZRmoZndq77giy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yfSZRmoZndq77giy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yfSZRmoZndq77giy rect.text{fill:none;stroke-width:0;}#mermaid-svg-yfSZRmoZndq77giy .icon-shape,#mermaid-svg-yfSZRmoZndq77giy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yfSZRmoZndq77giy .icon-shape p,#mermaid-svg-yfSZRmoZndq77giy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yfSZRmoZndq77giy .icon-shape .label rect,#mermaid-svg-yfSZRmoZndq77giy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yfSZRmoZndq77giy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yfSZRmoZndq77giy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yfSZRmoZndq77giy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户点击卡片
触发 onFlip
Zustand: flipCard()
isFlipped = !isFlipped
Framer Motion

animate={{ rotateY: 180 }}
CSS: backface-visibility: hidden
卡片翻转展示背面

5.5 列表模式(WordListTab)

#mermaid-svg-WMCTEnOPRuzNsEsr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WMCTEnOPRuzNsEsr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WMCTEnOPRuzNsEsr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WMCTEnOPRuzNsEsr .error-icon{fill:#552222;}#mermaid-svg-WMCTEnOPRuzNsEsr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WMCTEnOPRuzNsEsr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WMCTEnOPRuzNsEsr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WMCTEnOPRuzNsEsr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WMCTEnOPRuzNsEsr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WMCTEnOPRuzNsEsr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WMCTEnOPRuzNsEsr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WMCTEnOPRuzNsEsr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WMCTEnOPRuzNsEsr .marker.cross{stroke:#333333;}#mermaid-svg-WMCTEnOPRuzNsEsr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WMCTEnOPRuzNsEsr p{margin:0;}#mermaid-svg-WMCTEnOPRuzNsEsr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WMCTEnOPRuzNsEsr .cluster-label text{fill:#333;}#mermaid-svg-WMCTEnOPRuzNsEsr .cluster-label span{color:#333;}#mermaid-svg-WMCTEnOPRuzNsEsr .cluster-label span p{background-color:transparent;}#mermaid-svg-WMCTEnOPRuzNsEsr .label text,#mermaid-svg-WMCTEnOPRuzNsEsr span{fill:#333;color:#333;}#mermaid-svg-WMCTEnOPRuzNsEsr .node rect,#mermaid-svg-WMCTEnOPRuzNsEsr .node circle,#mermaid-svg-WMCTEnOPRuzNsEsr .node ellipse,#mermaid-svg-WMCTEnOPRuzNsEsr .node polygon,#mermaid-svg-WMCTEnOPRuzNsEsr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WMCTEnOPRuzNsEsr .rough-node .label text,#mermaid-svg-WMCTEnOPRuzNsEsr .node .label text,#mermaid-svg-WMCTEnOPRuzNsEsr .image-shape .label,#mermaid-svg-WMCTEnOPRuzNsEsr .icon-shape .label{text-anchor:middle;}#mermaid-svg-WMCTEnOPRuzNsEsr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WMCTEnOPRuzNsEsr .rough-node .label,#mermaid-svg-WMCTEnOPRuzNsEsr .node .label,#mermaid-svg-WMCTEnOPRuzNsEsr .image-shape .label,#mermaid-svg-WMCTEnOPRuzNsEsr .icon-shape .label{text-align:center;}#mermaid-svg-WMCTEnOPRuzNsEsr .node.clickable{cursor:pointer;}#mermaid-svg-WMCTEnOPRuzNsEsr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WMCTEnOPRuzNsEsr .arrowheadPath{fill:#333333;}#mermaid-svg-WMCTEnOPRuzNsEsr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WMCTEnOPRuzNsEsr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WMCTEnOPRuzNsEsr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WMCTEnOPRuzNsEsr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WMCTEnOPRuzNsEsr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WMCTEnOPRuzNsEsr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WMCTEnOPRuzNsEsr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WMCTEnOPRuzNsEsr .cluster text{fill:#333;}#mermaid-svg-WMCTEnOPRuzNsEsr .cluster span{color:#333;}#mermaid-svg-WMCTEnOPRuzNsEsr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WMCTEnOPRuzNsEsr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WMCTEnOPRuzNsEsr rect.text{fill:none;stroke-width:0;}#mermaid-svg-WMCTEnOPRuzNsEsr .icon-shape,#mermaid-svg-WMCTEnOPRuzNsEsr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WMCTEnOPRuzNsEsr .icon-shape p,#mermaid-svg-WMCTEnOPRuzNsEsr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WMCTEnOPRuzNsEsr .icon-shape .label rect,#mermaid-svg-WMCTEnOPRuzNsEsr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WMCTEnOPRuzNsEsr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WMCTEnOPRuzNsEsr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WMCTEnOPRuzNsEsr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} WordListTab
搜索栏

单词/释义/标签
收藏筛选
分类标签栏

横向滚动
单词列表

ScrollArea 虚拟滚动
单词条目
单词 + 音标 + 状态标签
核心释义
掌握/熟悉按钮 + 分类标签
收藏按钮

性能优化:

  • 分页加载:初始显示 50 词,点击"加载更多"增量加载
  • useMemo 缓存过滤结果
  • ScrollArea 优化长列表滚动性能

5.6 测验模式(QuizMode)

#mermaid-svg-CvqqVTuxDFbjqxv6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CvqqVTuxDFbjqxv6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CvqqVTuxDFbjqxv6 .error-icon{fill:#552222;}#mermaid-svg-CvqqVTuxDFbjqxv6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CvqqVTuxDFbjqxv6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CvqqVTuxDFbjqxv6 .marker.cross{stroke:#333333;}#mermaid-svg-CvqqVTuxDFbjqxv6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CvqqVTuxDFbjqxv6 p{margin:0;}#mermaid-svg-CvqqVTuxDFbjqxv6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CvqqVTuxDFbjqxv6 .cluster-label text{fill:#333;}#mermaid-svg-CvqqVTuxDFbjqxv6 .cluster-label span{color:#333;}#mermaid-svg-CvqqVTuxDFbjqxv6 .cluster-label span p{background-color:transparent;}#mermaid-svg-CvqqVTuxDFbjqxv6 .label text,#mermaid-svg-CvqqVTuxDFbjqxv6 span{fill:#333;color:#333;}#mermaid-svg-CvqqVTuxDFbjqxv6 .node rect,#mermaid-svg-CvqqVTuxDFbjqxv6 .node circle,#mermaid-svg-CvqqVTuxDFbjqxv6 .node ellipse,#mermaid-svg-CvqqVTuxDFbjqxv6 .node polygon,#mermaid-svg-CvqqVTuxDFbjqxv6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CvqqVTuxDFbjqxv6 .rough-node .label text,#mermaid-svg-CvqqVTuxDFbjqxv6 .node .label text,#mermaid-svg-CvqqVTuxDFbjqxv6 .image-shape .label,#mermaid-svg-CvqqVTuxDFbjqxv6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-CvqqVTuxDFbjqxv6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CvqqVTuxDFbjqxv6 .rough-node .label,#mermaid-svg-CvqqVTuxDFbjqxv6 .node .label,#mermaid-svg-CvqqVTuxDFbjqxv6 .image-shape .label,#mermaid-svg-CvqqVTuxDFbjqxv6 .icon-shape .label{text-align:center;}#mermaid-svg-CvqqVTuxDFbjqxv6 .node.clickable{cursor:pointer;}#mermaid-svg-CvqqVTuxDFbjqxv6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CvqqVTuxDFbjqxv6 .arrowheadPath{fill:#333333;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CvqqVTuxDFbjqxv6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CvqqVTuxDFbjqxv6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CvqqVTuxDFbjqxv6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CvqqVTuxDFbjqxv6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CvqqVTuxDFbjqxv6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CvqqVTuxDFbjqxv6 .cluster text{fill:#333;}#mermaid-svg-CvqqVTuxDFbjqxv6 .cluster span{color:#333;}#mermaid-svg-CvqqVTuxDFbjqxv6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CvqqVTuxDFbjqxv6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CvqqVTuxDFbjqxv6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-CvqqVTuxDFbjqxv6 .icon-shape,#mermaid-svg-CvqqVTuxDFbjqxv6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CvqqVTuxDFbjqxv6 .icon-shape p,#mermaid-svg-CvqqVTuxDFbjqxv6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CvqqVTuxDFbjqxv6 .icon-shape .label rect,#mermaid-svg-CvqqVTuxDFbjqxv6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CvqqVTuxDFbjqxv6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CvqqVTuxDFbjqxv6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CvqqVTuxDFbjqxv6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 最后一题
QuizMode
题目生成

随机 20 题
当前题目
单词卡片

单词 + 音标
四个选项

1 正确 + 3 干扰项
用户选择
正确

绿色高亮 + 记忆提示
错误

红色高亮 + 显示正确答案
下一题
结果页

得分 + 正确率 + 评价

干扰项生成算法:

  1. 从当前分类中随机选取 3 个不同单词
  2. 与正确答案一起随机排序
  3. 每轮测验重新生成(通过 quizKey 触发 useMemo 重新计算)

5.7 个人中心(ProfileTab)

#mermaid-svg-1opQytN0aQDruZqH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1opQytN0aQDruZqH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1opQytN0aQDruZqH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1opQytN0aQDruZqH .error-icon{fill:#552222;}#mermaid-svg-1opQytN0aQDruZqH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1opQytN0aQDruZqH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1opQytN0aQDruZqH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1opQytN0aQDruZqH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1opQytN0aQDruZqH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1opQytN0aQDruZqH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1opQytN0aQDruZqH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1opQytN0aQDruZqH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1opQytN0aQDruZqH .marker.cross{stroke:#333333;}#mermaid-svg-1opQytN0aQDruZqH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1opQytN0aQDruZqH p{margin:0;}#mermaid-svg-1opQytN0aQDruZqH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-1opQytN0aQDruZqH .cluster-label text{fill:#333;}#mermaid-svg-1opQytN0aQDruZqH .cluster-label span{color:#333;}#mermaid-svg-1opQytN0aQDruZqH .cluster-label span p{background-color:transparent;}#mermaid-svg-1opQytN0aQDruZqH .label text,#mermaid-svg-1opQytN0aQDruZqH span{fill:#333;color:#333;}#mermaid-svg-1opQytN0aQDruZqH .node rect,#mermaid-svg-1opQytN0aQDruZqH .node circle,#mermaid-svg-1opQytN0aQDruZqH .node ellipse,#mermaid-svg-1opQytN0aQDruZqH .node polygon,#mermaid-svg-1opQytN0aQDruZqH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1opQytN0aQDruZqH .rough-node .label text,#mermaid-svg-1opQytN0aQDruZqH .node .label text,#mermaid-svg-1opQytN0aQDruZqH .image-shape .label,#mermaid-svg-1opQytN0aQDruZqH .icon-shape .label{text-anchor:middle;}#mermaid-svg-1opQytN0aQDruZqH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-1opQytN0aQDruZqH .rough-node .label,#mermaid-svg-1opQytN0aQDruZqH .node .label,#mermaid-svg-1opQytN0aQDruZqH .image-shape .label,#mermaid-svg-1opQytN0aQDruZqH .icon-shape .label{text-align:center;}#mermaid-svg-1opQytN0aQDruZqH .node.clickable{cursor:pointer;}#mermaid-svg-1opQytN0aQDruZqH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-1opQytN0aQDruZqH .arrowheadPath{fill:#333333;}#mermaid-svg-1opQytN0aQDruZqH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-1opQytN0aQDruZqH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-1opQytN0aQDruZqH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1opQytN0aQDruZqH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-1opQytN0aQDruZqH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1opQytN0aQDruZqH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-1opQytN0aQDruZqH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1opQytN0aQDruZqH .cluster text{fill:#333;}#mermaid-svg-1opQytN0aQDruZqH .cluster span{color:#333;}#mermaid-svg-1opQytN0aQDruZqH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-1opQytN0aQDruZqH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1opQytN0aQDruZqH rect.text{fill:none;stroke-width:0;}#mermaid-svg-1opQytN0aQDruZqH .icon-shape,#mermaid-svg-1opQytN0aQDruZqH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-1opQytN0aQDruZqH .icon-shape p,#mermaid-svg-1opQytN0aQDruZqH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-1opQytN0aQDruZqH .icon-shape .label rect,#mermaid-svg-1opQytN0aQDruZqH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-1opQytN0aQDruZqH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1opQytN0aQDruZqH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1opQytN0aQDruZqH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ProfileTab
头像区

考研战士
总体进度

已掌握百分比 + 三列统计
分类进度

各分类掌握情况条形图
学习统计

今日已学/目标/收藏
每日目标设置

20/30/50/80/100
重置进度


6. 数据流设计

6.1 词汇数据流

#mermaid-svg-hvqBJvL2LJ4lLQEk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hvqBJvL2LJ4lLQEk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hvqBJvL2LJ4lLQEk .error-icon{fill:#552222;}#mermaid-svg-hvqBJvL2LJ4lLQEk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hvqBJvL2LJ4lLQEk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hvqBJvL2LJ4lLQEk .marker.cross{stroke:#333333;}#mermaid-svg-hvqBJvL2LJ4lLQEk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hvqBJvL2LJ4lLQEk p{margin:0;}#mermaid-svg-hvqBJvL2LJ4lLQEk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hvqBJvL2LJ4lLQEk .cluster-label text{fill:#333;}#mermaid-svg-hvqBJvL2LJ4lLQEk .cluster-label span{color:#333;}#mermaid-svg-hvqBJvL2LJ4lLQEk .cluster-label span p{background-color:transparent;}#mermaid-svg-hvqBJvL2LJ4lLQEk .label text,#mermaid-svg-hvqBJvL2LJ4lLQEk span{fill:#333;color:#333;}#mermaid-svg-hvqBJvL2LJ4lLQEk .node rect,#mermaid-svg-hvqBJvL2LJ4lLQEk .node circle,#mermaid-svg-hvqBJvL2LJ4lLQEk .node ellipse,#mermaid-svg-hvqBJvL2LJ4lLQEk .node polygon,#mermaid-svg-hvqBJvL2LJ4lLQEk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hvqBJvL2LJ4lLQEk .rough-node .label text,#mermaid-svg-hvqBJvL2LJ4lLQEk .node .label text,#mermaid-svg-hvqBJvL2LJ4lLQEk .image-shape .label,#mermaid-svg-hvqBJvL2LJ4lLQEk .icon-shape .label{text-anchor:middle;}#mermaid-svg-hvqBJvL2LJ4lLQEk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hvqBJvL2LJ4lLQEk .rough-node .label,#mermaid-svg-hvqBJvL2LJ4lLQEk .node .label,#mermaid-svg-hvqBJvL2LJ4lLQEk .image-shape .label,#mermaid-svg-hvqBJvL2LJ4lLQEk .icon-shape .label{text-align:center;}#mermaid-svg-hvqBJvL2LJ4lLQEk .node.clickable{cursor:pointer;}#mermaid-svg-hvqBJvL2LJ4lLQEk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hvqBJvL2LJ4lLQEk .arrowheadPath{fill:#333333;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hvqBJvL2LJ4lLQEk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hvqBJvL2LJ4lLQEk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hvqBJvL2LJ4lLQEk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hvqBJvL2LJ4lLQEk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hvqBJvL2LJ4lLQEk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hvqBJvL2LJ4lLQEk .cluster text{fill:#333;}#mermaid-svg-hvqBJvL2LJ4lLQEk .cluster span{color:#333;}#mermaid-svg-hvqBJvL2LJ4lLQEk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hvqBJvL2LJ4lLQEk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hvqBJvL2LJ4lLQEk rect.text{fill:none;stroke-width:0;}#mermaid-svg-hvqBJvL2LJ4lLQEk .icon-shape,#mermaid-svg-hvqBJvL2LJ4lLQEk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hvqBJvL2LJ4lLQEk .icon-shape p,#mermaid-svg-hvqBJvL2LJ4lLQEk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hvqBJvL2LJ4lLQEk .icon-shape .label rect,#mermaid-svg-hvqBJvL2LJ4lLQEk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hvqBJvL2LJ4lLQEk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hvqBJvL2LJ4lLQEk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hvqBJvL2LJ4lLQEk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 14 个数据源
vocabulary.ts
vocab-core-*.ts
vocab-ac ~ tz.ts
vocab-supplement*.ts
index.ts

合并 + 去重 + 分类分配
allVocabulary\[\]

~5500+ 词
page.tsx
Zustand Store
各 Tab 组件

6.2 状态数据流

#mermaid-svg-m8oxCbQNiKg7St2W{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-m8oxCbQNiKg7St2W .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-m8oxCbQNiKg7St2W .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-m8oxCbQNiKg7St2W .error-icon{fill:#552222;}#mermaid-svg-m8oxCbQNiKg7St2W .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-m8oxCbQNiKg7St2W .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-m8oxCbQNiKg7St2W .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-m8oxCbQNiKg7St2W .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-m8oxCbQNiKg7St2W .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-m8oxCbQNiKg7St2W .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-m8oxCbQNiKg7St2W .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-m8oxCbQNiKg7St2W .marker{fill:#333333;stroke:#333333;}#mermaid-svg-m8oxCbQNiKg7St2W .marker.cross{stroke:#333333;}#mermaid-svg-m8oxCbQNiKg7St2W svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-m8oxCbQNiKg7St2W p{margin:0;}#mermaid-svg-m8oxCbQNiKg7St2W .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-m8oxCbQNiKg7St2W .cluster-label text{fill:#333;}#mermaid-svg-m8oxCbQNiKg7St2W .cluster-label span{color:#333;}#mermaid-svg-m8oxCbQNiKg7St2W .cluster-label span p{background-color:transparent;}#mermaid-svg-m8oxCbQNiKg7St2W .label text,#mermaid-svg-m8oxCbQNiKg7St2W span{fill:#333;color:#333;}#mermaid-svg-m8oxCbQNiKg7St2W .node rect,#mermaid-svg-m8oxCbQNiKg7St2W .node circle,#mermaid-svg-m8oxCbQNiKg7St2W .node ellipse,#mermaid-svg-m8oxCbQNiKg7St2W .node polygon,#mermaid-svg-m8oxCbQNiKg7St2W .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-m8oxCbQNiKg7St2W .rough-node .label text,#mermaid-svg-m8oxCbQNiKg7St2W .node .label text,#mermaid-svg-m8oxCbQNiKg7St2W .image-shape .label,#mermaid-svg-m8oxCbQNiKg7St2W .icon-shape .label{text-anchor:middle;}#mermaid-svg-m8oxCbQNiKg7St2W .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-m8oxCbQNiKg7St2W .rough-node .label,#mermaid-svg-m8oxCbQNiKg7St2W .node .label,#mermaid-svg-m8oxCbQNiKg7St2W .image-shape .label,#mermaid-svg-m8oxCbQNiKg7St2W .icon-shape .label{text-align:center;}#mermaid-svg-m8oxCbQNiKg7St2W .node.clickable{cursor:pointer;}#mermaid-svg-m8oxCbQNiKg7St2W .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-m8oxCbQNiKg7St2W .arrowheadPath{fill:#333333;}#mermaid-svg-m8oxCbQNiKg7St2W .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-m8oxCbQNiKg7St2W .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-m8oxCbQNiKg7St2W .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-m8oxCbQNiKg7St2W .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-m8oxCbQNiKg7St2W .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-m8oxCbQNiKg7St2W .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-m8oxCbQNiKg7St2W .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-m8oxCbQNiKg7St2W .cluster text{fill:#333;}#mermaid-svg-m8oxCbQNiKg7St2W .cluster span{color:#333;}#mermaid-svg-m8oxCbQNiKg7St2W div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-m8oxCbQNiKg7St2W .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-m8oxCbQNiKg7St2W rect.text{fill:none;stroke-width:0;}#mermaid-svg-m8oxCbQNiKg7St2W .icon-shape,#mermaid-svg-m8oxCbQNiKg7St2W .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-m8oxCbQNiKg7St2W .icon-shape p,#mermaid-svg-m8oxCbQNiKg7St2W .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-m8oxCbQNiKg7St2W .icon-shape .label rect,#mermaid-svg-m8oxCbQNiKg7St2W .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-m8oxCbQNiKg7St2W .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-m8oxCbQNiKg7St2W .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-m8oxCbQNiKg7St2W :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 全局状态 (Zustand)
currentCategory
currentWordIndex
isFlipped
masteredWords\[\]
familiarWords\[\]
bookmarkedWords\[\]
quizState
searchQuery
dailyGoal / dailyLearned
vocab-store.ts
HomeTab
FlashcardTab
WordListTab
QuizMode
ProfileTab


7. 核心算法与逻辑

7.1 数据去重与合并

#mermaid-svg-QkMz5Ci5XbVODOjQ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QkMz5Ci5XbVODOjQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QkMz5Ci5XbVODOjQ .error-icon{fill:#552222;}#mermaid-svg-QkMz5Ci5XbVODOjQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QkMz5Ci5XbVODOjQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QkMz5Ci5XbVODOjQ .marker.cross{stroke:#333333;}#mermaid-svg-QkMz5Ci5XbVODOjQ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QkMz5Ci5XbVODOjQ p{margin:0;}#mermaid-svg-QkMz5Ci5XbVODOjQ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QkMz5Ci5XbVODOjQ .cluster-label text{fill:#333;}#mermaid-svg-QkMz5Ci5XbVODOjQ .cluster-label span{color:#333;}#mermaid-svg-QkMz5Ci5XbVODOjQ .cluster-label span p{background-color:transparent;}#mermaid-svg-QkMz5Ci5XbVODOjQ .label text,#mermaid-svg-QkMz5Ci5XbVODOjQ span{fill:#333;color:#333;}#mermaid-svg-QkMz5Ci5XbVODOjQ .node rect,#mermaid-svg-QkMz5Ci5XbVODOjQ .node circle,#mermaid-svg-QkMz5Ci5XbVODOjQ .node ellipse,#mermaid-svg-QkMz5Ci5XbVODOjQ .node polygon,#mermaid-svg-QkMz5Ci5XbVODOjQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QkMz5Ci5XbVODOjQ .rough-node .label text,#mermaid-svg-QkMz5Ci5XbVODOjQ .node .label text,#mermaid-svg-QkMz5Ci5XbVODOjQ .image-shape .label,#mermaid-svg-QkMz5Ci5XbVODOjQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-QkMz5Ci5XbVODOjQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QkMz5Ci5XbVODOjQ .rough-node .label,#mermaid-svg-QkMz5Ci5XbVODOjQ .node .label,#mermaid-svg-QkMz5Ci5XbVODOjQ .image-shape .label,#mermaid-svg-QkMz5Ci5XbVODOjQ .icon-shape .label{text-align:center;}#mermaid-svg-QkMz5Ci5XbVODOjQ .node.clickable{cursor:pointer;}#mermaid-svg-QkMz5Ci5XbVODOjQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QkMz5Ci5XbVODOjQ .arrowheadPath{fill:#333333;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QkMz5Ci5XbVODOjQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QkMz5Ci5XbVODOjQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QkMz5Ci5XbVODOjQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QkMz5Ci5XbVODOjQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QkMz5Ci5XbVODOjQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QkMz5Ci5XbVODOjQ .cluster text{fill:#333;}#mermaid-svg-QkMz5Ci5XbVODOjQ .cluster span{color:#333;}#mermaid-svg-QkMz5Ci5XbVODOjQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QkMz5Ci5XbVODOjQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QkMz5Ci5XbVODOjQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-QkMz5Ci5XbVODOjQ .icon-shape,#mermaid-svg-QkMz5Ci5XbVODOjQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QkMz5Ci5XbVODOjQ .icon-shape p,#mermaid-svg-QkMz5Ci5XbVODOjQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QkMz5Ci5XbVODOjQ .icon-shape .label rect,#mermaid-svg-QkMz5Ci5XbVODOjQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QkMz5Ci5XbVODOjQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QkMz5Ci5XbVODOjQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QkMz5Ci5XbVODOjQ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} No
Yes
14 个词汇源数组
按优先级排序
遍历所有单词
seen.has

word.toLowerCase()?
存入 seen Map
跳过(保留更详细的版本)
分配顺序 ID: w1, w2, ...
assignCategories

自动多分类分配
allVocabulary\[\]

优先级规则:

  1. vocabulary.ts(最详细,含例句和记忆提示)
  2. vocab-core-*.ts(核心词扩展)
  3. vocab-ac.ts ~ vocab-tz.ts(按字母分区)
  4. vocab-supplement*.ts(补充词汇)

7.2 自动分类分配算法

基于单词的 categoryfrequencytags 自动分配多分类标签:

条件 分配分类
core + freq >= 5 reading, writing
core + freq >= 4 + 动词/名词/高频 reading
core + 标签含 易混/辨析/多义/用法 cloze
core + 标签含 搭配/写作/虚拟语气 writing
core + freq >= 4 + 形容词 reading, writing
basic + freq >= 4 reading
reading + freq >= 4 writing
writing reading
cloze + freq >= 4 reading

7.3 测验干扰项生成

#mermaid-svg-fh2V5NQXRuXGbbnC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fh2V5NQXRuXGbbnC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fh2V5NQXRuXGbbnC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fh2V5NQXRuXGbbnC .error-icon{fill:#552222;}#mermaid-svg-fh2V5NQXRuXGbbnC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fh2V5NQXRuXGbbnC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fh2V5NQXRuXGbbnC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fh2V5NQXRuXGbbnC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fh2V5NQXRuXGbbnC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fh2V5NQXRuXGbbnC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fh2V5NQXRuXGbbnC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fh2V5NQXRuXGbbnC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fh2V5NQXRuXGbbnC .marker.cross{stroke:#333333;}#mermaid-svg-fh2V5NQXRuXGbbnC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fh2V5NQXRuXGbbnC p{margin:0;}#mermaid-svg-fh2V5NQXRuXGbbnC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fh2V5NQXRuXGbbnC .cluster-label text{fill:#333;}#mermaid-svg-fh2V5NQXRuXGbbnC .cluster-label span{color:#333;}#mermaid-svg-fh2V5NQXRuXGbbnC .cluster-label span p{background-color:transparent;}#mermaid-svg-fh2V5NQXRuXGbbnC .label text,#mermaid-svg-fh2V5NQXRuXGbbnC span{fill:#333;color:#333;}#mermaid-svg-fh2V5NQXRuXGbbnC .node rect,#mermaid-svg-fh2V5NQXRuXGbbnC .node circle,#mermaid-svg-fh2V5NQXRuXGbbnC .node ellipse,#mermaid-svg-fh2V5NQXRuXGbbnC .node polygon,#mermaid-svg-fh2V5NQXRuXGbbnC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fh2V5NQXRuXGbbnC .rough-node .label text,#mermaid-svg-fh2V5NQXRuXGbbnC .node .label text,#mermaid-svg-fh2V5NQXRuXGbbnC .image-shape .label,#mermaid-svg-fh2V5NQXRuXGbbnC .icon-shape .label{text-anchor:middle;}#mermaid-svg-fh2V5NQXRuXGbbnC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fh2V5NQXRuXGbbnC .rough-node .label,#mermaid-svg-fh2V5NQXRuXGbbnC .node .label,#mermaid-svg-fh2V5NQXRuXGbbnC .image-shape .label,#mermaid-svg-fh2V5NQXRuXGbbnC .icon-shape .label{text-align:center;}#mermaid-svg-fh2V5NQXRuXGbbnC .node.clickable{cursor:pointer;}#mermaid-svg-fh2V5NQXRuXGbbnC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fh2V5NQXRuXGbbnC .arrowheadPath{fill:#333333;}#mermaid-svg-fh2V5NQXRuXGbbnC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fh2V5NQXRuXGbbnC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fh2V5NQXRuXGbbnC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fh2V5NQXRuXGbbnC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fh2V5NQXRuXGbbnC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fh2V5NQXRuXGbbnC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fh2V5NQXRuXGbbnC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fh2V5NQXRuXGbbnC .cluster text{fill:#333;}#mermaid-svg-fh2V5NQXRuXGbbnC .cluster span{color:#333;}#mermaid-svg-fh2V5NQXRuXGbbnC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fh2V5NQXRuXGbbnC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fh2V5NQXRuXGbbnC rect.text{fill:none;stroke-width:0;}#mermaid-svg-fh2V5NQXRuXGbbnC .icon-shape,#mermaid-svg-fh2V5NQXRuXGbbnC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fh2V5NQXRuXGbbnC .icon-shape p,#mermaid-svg-fh2V5NQXRuXGbbnC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fh2V5NQXRuXGbbnC .icon-shape .label rect,#mermaid-svg-fh2V5NQXRuXGbbnC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fh2V5NQXRuXGbbnC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fh2V5NQXRuXGbbnC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fh2V5NQXRuXGbbnC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 选取当前分类单词
随机打乱 shuffleArray
取前 20 个作为题目
每题生成选项
从全部分类单词中

过滤掉当前单词
随机选 3 个错误选项
与正确答案合并

再次随机排序


8. 样式与主题设计

8.1 色彩系统

用途 颜色值 说明
主色(微信绿) #07C160 品牌主色,用于按钮、进度条、选中状态
主色深 #06AD56 渐变深色端
主色浅 #E8F8EE 背景、浅色卡片
核心词 #F59E0B 琥珀色
阅读高频 #8B5CF6 紫色
完形高频 #EC4899 粉色
写作加分 #06B6D4 青色
基础词 #6B7280 灰色

8.2 布局规范

  • 最大宽度max-w-lg mx-auto(移动端优先,桌面端居中)
  • 底部安全区pb-[max(0.25rem,env(safe-area-inset-bottom))]
  • 卡片圆角rounded-2xl / rounded-xl
  • 按钮圆角rounded-full
  • 间距系统:基于 Tailwind 默认间距

9. 构建与部署

9.1 构建配置

typescript 复制代码
// next.config.ts
const nextConfig: NextConfig = {
  output: "standalone",      // 独立输出,适合容器化部署
  typescript: {
    ignoreBuildErrors: true, // 忽略 TS 错误(快速构建)
  },
  reactStrictMode: false,
};

9.2 构建流程

#mermaid-svg-uLOqiofrVnev1gPd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uLOqiofrVnev1gPd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uLOqiofrVnev1gPd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uLOqiofrVnev1gPd .error-icon{fill:#552222;}#mermaid-svg-uLOqiofrVnev1gPd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uLOqiofrVnev1gPd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uLOqiofrVnev1gPd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uLOqiofrVnev1gPd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uLOqiofrVnev1gPd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uLOqiofrVnev1gPd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uLOqiofrVnev1gPd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uLOqiofrVnev1gPd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uLOqiofrVnev1gPd .marker.cross{stroke:#333333;}#mermaid-svg-uLOqiofrVnev1gPd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uLOqiofrVnev1gPd p{margin:0;}#mermaid-svg-uLOqiofrVnev1gPd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uLOqiofrVnev1gPd .cluster-label text{fill:#333;}#mermaid-svg-uLOqiofrVnev1gPd .cluster-label span{color:#333;}#mermaid-svg-uLOqiofrVnev1gPd .cluster-label span p{background-color:transparent;}#mermaid-svg-uLOqiofrVnev1gPd .label text,#mermaid-svg-uLOqiofrVnev1gPd span{fill:#333;color:#333;}#mermaid-svg-uLOqiofrVnev1gPd .node rect,#mermaid-svg-uLOqiofrVnev1gPd .node circle,#mermaid-svg-uLOqiofrVnev1gPd .node ellipse,#mermaid-svg-uLOqiofrVnev1gPd .node polygon,#mermaid-svg-uLOqiofrVnev1gPd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uLOqiofrVnev1gPd .rough-node .label text,#mermaid-svg-uLOqiofrVnev1gPd .node .label text,#mermaid-svg-uLOqiofrVnev1gPd .image-shape .label,#mermaid-svg-uLOqiofrVnev1gPd .icon-shape .label{text-anchor:middle;}#mermaid-svg-uLOqiofrVnev1gPd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uLOqiofrVnev1gPd .rough-node .label,#mermaid-svg-uLOqiofrVnev1gPd .node .label,#mermaid-svg-uLOqiofrVnev1gPd .image-shape .label,#mermaid-svg-uLOqiofrVnev1gPd .icon-shape .label{text-align:center;}#mermaid-svg-uLOqiofrVnev1gPd .node.clickable{cursor:pointer;}#mermaid-svg-uLOqiofrVnev1gPd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uLOqiofrVnev1gPd .arrowheadPath{fill:#333333;}#mermaid-svg-uLOqiofrVnev1gPd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uLOqiofrVnev1gPd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uLOqiofrVnev1gPd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uLOqiofrVnev1gPd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uLOqiofrVnev1gPd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uLOqiofrVnev1gPd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uLOqiofrVnev1gPd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uLOqiofrVnev1gPd .cluster text{fill:#333;}#mermaid-svg-uLOqiofrVnev1gPd .cluster span{color:#333;}#mermaid-svg-uLOqiofrVnev1gPd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uLOqiofrVnev1gPd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uLOqiofrVnev1gPd rect.text{fill:none;stroke-width:0;}#mermaid-svg-uLOqiofrVnev1gPd .icon-shape,#mermaid-svg-uLOqiofrVnev1gPd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uLOqiofrVnev1gPd .icon-shape p,#mermaid-svg-uLOqiofrVnev1gPd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uLOqiofrVnev1gPd .icon-shape .label rect,#mermaid-svg-uLOqiofrVnev1gPd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uLOqiofrVnev1gPd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uLOqiofrVnev1gPd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uLOqiofrVnev1gPd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} bun install
next build
生成 .next/standalone
复制 static 到 standalone
复制 public 到 standalone
bun .next/standalone/server.js

9.3 部署方式

方式 说明
Standalone 输出独立 Node.js 应用,无需依赖 node_modules
Caddy 通过 Caddyfile 配置反向代理
Docker 可基于 node:alpineoven/bun 镜像构建

10. 待优化与扩展点

10.1 当前局限性

  1. API 未使用src/app/api/route.ts 仅为占位,Prisma/SQLite 未深度集成
  2. 无后端同步:学习进度仅保存在 localStorage,无法跨设备同步
  3. 无用户系统next-auth 已安装但未配置,无登录/注册功能
  4. 数据体积大:所有词汇数据打包在 JS 中,首屏加载较重
  5. 无服务端渲染page.tsx 标记 "use client",丧失 SSR 优势

10.2 建议扩展方向

方向 实现思路
后端 API 将词汇数据迁移到数据库,通过 API 分页获取
用户系统 配置 next-auth,支持 OAuth 登录,同步学习进度
数据懒加载 按分类/字母分区动态导入词汇数据
复习算法 引入艾宾浩斯遗忘曲线,智能推荐复习单词
语音播放 集成 Web Speech API 或第三方 TTS 服务
暗黑模式 利用 next-themes 实现主题切换(已安装)
国际化 利用 next-intl 支持多语言(已安装)

11. 附录

11.1 词汇数据统计

数据文件 行数 说明
vocabulary.ts 1704 核心词汇(最详细)
vocab-io.ts 1067 I-O 分区词汇
vocab-ps.ts 853 P-S 分区词汇
vocab-dh.ts 735 D-H 分区词汇
vocab-ac.ts 720 A-C 分区词汇
vocab-tz.ts 725 T-Z 分区词汇
vocab-rcw.ts 623 额外补充
vocab-supplement-al.ts 535 A-L 补充
vocab-core-ae.ts 376 核心词 A-E
vocab-core-fn.ts 365 核心词 F-N
vocab-core-oz.ts 405 核心词 O-Z
vocab-core-expanded.ts 328 核心词扩展
vocab-extra.ts 400 额外词汇
vocab-supplement-mz.ts 286 M-Z 补充
vocab-final-supplement.ts 93 最终补充
总计 ~9387 行 ~5500+ 去重词汇

11.2 依赖版本锁定

关键生产依赖版本:

  • next: ^16.1.1
  • react: ^19.0.0
  • tailwindcss: ^4
  • zustand: ^5.0.6
  • framer-motion: ^12.23.2
  • @prisma/client: ^6.11.1
相关推荐
打瞌睡的朱尤18 小时前
微信小程序(黑马)Day1~3
微信小程序·小程序
郑州光合科技余经理1 天前
海外版外卖系统:如何快速搭建国际化外卖平台
java·开发语言·前端·人工智能·小程序·系统架构·php
小北的AI科技分享1 天前
2026年小程序平台深度解析:全场景数字化经营工具选型指南
小程序·小程序平台
酉鬼女又兒1 天前
零基础入门计算机网络:物理层核心知识全解——传输方式分类、编码调制原理与信道极限容量计算
网络·计算机网络·考研·职场和发展·分类·数据挖掘·php
酉鬼女又兒1 天前
零基础入门计算机网络物理层:核心概念、传输媒体、传输方式、编码调制与信道极限容量完整知识点总结
开发语言·网络·计算机网络·考研·职场和发展·php·信息与通信
川石课堂软件测试1 天前
什么是埋点测试,app埋点测试怎么做?
功能测试·测试工具·华为·小程序·单元测试·appium·harmonyos
游戏开发爱好者81 天前
Linux 自动上传 App Store Connect:把 IPA 上传流程接进CI工作流
linux·运维·ios·ci/cd·小程序·uni-app·iphone
暗冰ཏོ1 天前
《uni-app 跨端开发完整指南:从基础入门到 H5、小程序、App 发布上线》
前端·小程序·uni-app·vue·html5
weixin_lynhgworld1 天前
品牌私域版|品牌专属盲盒小程序,沉淀私域用户、提升品牌溢价
小程序