考研伴侣App完整开发记录

项目概述

考研伴侣是一个基于 Vue 3 + Vue Router + Vite + Tailwind CSS 构建的纯前端学习规划应用,专为考研学子设计。应用采用现代化的玻璃拟态(Glassmorphism)设计风格,支持深色/浅色模式切换,所有数据通过 LocalStorage 实现持久化存储。

GitHub 仓库https://github.com/dafenqirunrunrun/love-study-app

技术栈

技术 用途
Vue 3 前端框架(Composition API)
Vue Router 4 单页面应用路由
Vite 5 构建工具
Tailwind CSS 原子化CSS框架
LocalStorage 数据持久化存储
JavaScript (ES6+) 编程语言

核心功能模块

1. 首页概览

1.1 目标倒计时

支持自定义目标名称和日期,从硬编码改为响应式设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Settings.vue - 倒计时设置
const countdownSettings = ref({
eventName: '考研初试',
targetDate: '2025-12-21'
})

// 实时计算天数
const countdownDays = computed(() => {
const target = new Date(countdownSettings.value.targetDate)
const today = new Date()
const diff = target - today
return Math.max(0, Math.ceil(diff / (1000 * 60 * 60 * 24)))
})

用户可在设置中自定义目标名称(考研初试、面试、答辩等)和目标日期,首页实时显示倒计时天数。

1.2 今日任务时间轴

显示当日待办任务,支持优先级标记:

1
2
3
4
5
6
7
8
<!-- 任务时间轴 -->
<div class="timeline-item"
v-for="(task, index) in todayTasks"
:key="task.id || index"
:class="['priority-' + (task.priority || 'normal')]">
<div class="timeline-dot"></div>
<span class="task-text">{{ task.text }}</span>
</div>

1.3 统计数据卡片

四个核心统计卡片:

  • 今日专注:显示当日专注总时长
  • 今日打卡:显示当日习惯打卡数量
  • 完成任务:显示已完成/总任务数
  • 当前积分:显示用户积分余额

1.4 展开更多区域

包含三个小组件:

  • 每日一句:励志语录展示
  • 本周挑战:连续打卡和专注时长进度条
  • 学习记录:连续学习天数和总学习天数

⚠️ 问题修复:本周挑战和学习记录原本是硬编码数据,改为 LocalStorage 存储,确保初始化时可以正确重置。

2. 任务管理

任务系统支持:

  • ✅ 创建/编辑/删除任务
  • ✅ 设置任务优先级(高/中/普通)
  • ✅ 设置截止日期
  • ✅ 标记任务分类(数学、英语、政治、专业课)
  • ✅ 一键完成任务
  • ✅ 筛选(全部/进行中/已完成)
  • ✅ 搜索功能
  • ✅ 撤销删除

3. 番茄钟专注

3.1 核心功能

1
2
3
4
5
6
7
// 番茄钟设置(可自定义)
const focusSettings = ref({
focus: 25, // 专注时长(分钟)
shortBreak: 5, // 短休息时长
longBreak: 15, // 长休息时长
goal: 8 // 每日目标次数
})
  • ⏱️ 专注计时:25分钟标准番茄钟(可自定义1-60分钟)
  • 休息提醒:短休息5分钟,长休息15分钟
  • 📊 专注统计:记录每次专注时长和完成次数
  • 🔔 音效提示:开始/结束/休息提醒

3.2 白噪音环境音

内置6种环境音效:

  • 🌧️ 雨声
  • 🌊 海浪
  • ☕ 咖啡厅
  • 🚂 火车
  • 🔥 壁炉
  • 🌿 森林

4. 习惯打卡系统

4.1 核心功能

  • 📅 每日习惯追踪
  • ✅ 一键打卡(带庆祝动画)
  • 🎨 自定义习惯图标和颜色
  • 📊 本周完成率环形图
  • 🌡️ GitHub风格热力图

4.2 热力图实现

1
2
3
4
5
6
7
8
9
10
11
12
13
// 计算热力图数据
const heatmapData = computed(() => {
const data = {}
const today = new Date()
for (let i = 364; i >= 0; i--) {
const date = new Date(today)
date.setDate(date.getDate() - i)
const dateStr = date.toISOString().split('T')[0]
const checkins = checkinHistory.value.filter(c => c.date === dateStr).length
data[dateStr] = Math.min(checkins, 4) // 最大值为4
}
return data
})

5. 日历视图

5.1 任务密度可视化

每个日期格子通过背景色深浅表示任务密度:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 任务密度级别
const getDensityLevel = (date) => {
const dateStr = date.toISOString().split('T')[0]
const taskCount = tasks.value.filter(t => {
const taskDate = t.date || t.createdAt?.split('T')[0]
return taskDate === dateStr
}).length

if (taskCount === 0) return 'none'
if (taskCount <= 2) return 'low'
if (taskCount <= 4) return 'medium'
if (taskCount <= 6) return 'high'
return 'full'
}

密度级别对应5种背景颜色,从浅到深表示任务数量由少到多。

6. 数据统计

6.1 周对比箭头

1
2
3
4
5
6
7
8
9
10
11
12
13
// 周同比计算
const comparison = computed(() => {
const thisWeek = thisWeekFocus.value
const lastWeek = lastWeekFocus.value

if (lastWeek === 0) return { percent: 0, direction: 'up' }
const change = ((thisWeek - lastWeek) / lastWeek) * 100

return {
percent: Math.abs(Math.round(change)),
direction: change >= 0 ? 'up' : 'down'
}
})

6.2 统计图表

  • 📈 专注时长趋势图
  • 📊 任务分类饼图
  • 🔥 连续学习天数统计
  • 📅 月度热力图

7. 积分中心

7.1 等级系统

5个等级,从低到高:

等级 名称 所需积分 称号
🥉 1级 新手 0-99 考研新手
📚 2级 学者 100-499 学习学者
🎓 3级 学霸 500-1999 考研学霸
🌟 4级 大咖 2000-4999 学习大咖
🏆 5级 传奇 5000+ 考研传奇

7.2 虚拟宠物

养成的虚拟宠物会根据饥饿值和心情值变化:

  • 🐱 饥饿值低 → 开心
  • 🐱 饥饿值高 → 饿肚子
  • 心情值随积分变化

7.3 奖励商店

支持按时间筛选:

  • 全部奖励
  • 本周获得
  • 本月获得

8. 设置页面

8.1 目标倒计时设置

1
2
3
4
设置 → 目标倒计时
├── 目标名称:自定义(如:考研初试、面试、答辩)
├── 目标日期:选择具体日期
└── 实时显示:距离目标还有 X 天

8.2 番茄钟设置

设置项 默认值 可调范围
专注时长 25分钟 1-60分钟
短休息 5分钟 1-30分钟
长休息 15分钟 1-60分钟
每日目标 8次 1-20次

8.3 数据管理

功能 说明
📤 导出数据 导出所有数据到JSON文件
📥 导入数据 从JSON文件导入数据
🚀 初始化 新用户重置所有学习数据

⚠️ 初始化说明:初始化会清除所有学习数据(任务、打卡、积分等),但保留基本设置(深色模式、番茄钟设置、倒计时设置)。

8.4 日间/夜间模式

一键切换深色/浅色主题,优化日间模式可见性:

1
2
3
4
5
6
7
8
9
/* 深色模式 */
:global(.dark) .setting-name {
color: #fff;
}

/* 浅色模式 */
.setting-name {
color: #1f2937;
}

数据存储结构

LocalStorage 键名对照表

键名 数据类型 说明
tasks Array 任务列表
focusHistory Object 专注历史记录
checkinHistory Array 打卡历史
lovePoints Number 当前积分
pointsHistory Array 积分变动记录
habits Array 习惯列表
dailyJournal Object 每日心得
journalMood Object 每日心情
journalHistory Array 心得历史
learningPlans Array 学习计划
unlockedBadges Array 已解锁徽章
focusSettings Object 番茄钟设置
countdownSettings Object 倒计时设置
weeklyChallenge Object 本周挑战数据
learningStats Object 学习统计数据
darkMode Boolean 深色模式开关
notificationSettings Object 通知设置

遇到的问题与解决方案

问题1:Home.vue 页面空白

错误信息

1
TypeError: b.value.filter is not a function

原因focusHistory 在不同页面存储格式不一致

  • 其他页面:Object 格式 { "日期": { minutes, sessions } }
  • Home.vue:期望 Array 格式

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
// 添加数据格式转换函数
const normalizeFocusHistory = (data) => {
if (!data) return []
if (Array.isArray(data)) return data
return Object.entries(data).map(([date, value]) => ({
date,
...value
}))
}

const focusHistoryRaw = ref(getFromStorage('focusHistory', {}))
const focusHistory = computed(() => normalizeFocusHistory(focusHistoryRaw.value))

问题2:MoreMenu.vue 点击无响应

原因:组件未正确接收 props 和 emit

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// MoreMenu.vue
const props = defineProps({
isOpen: { type: Boolean, default: false }
})

const emit = defineEmits(['close'])

watch(() => props.isOpen, (newVal) => {
isOpen.value = newVal
})

const close = () => {
isOpen.value = false
emit('close')
}

问题3:初始化后本周挑战和学习记录未清零

原因:这些数据是硬编码在 HTML 模板中的

解决方案

  1. 将硬编码改为响应式数据
  2. 添加 LocalStorage 存储
  3. 初始化时重置默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Home.vue
const weeklyChallenge = ref({
checkinStreak: 0,
checkinGoal: 5,
focusMinutes: 0,
focusGoalMinutes: 300
})

const learningStats = ref({
streakDays: 0,
totalDays: 0
})

// Settings.vue 初始化时
localStorage.setItem('weeklyChallenge', JSON.stringify({
checkinStreak: 0,
checkinGoal: 5,
focusMinutes: 0,
focusGoalMinutes: 300
}))
localStorage.setItem('learningStats', JSON.stringify({
streakDays: 0,
totalDays: 0
}))

问题4:日间模式下设置页面文字看不清

原因:CSS 样式只有深色模式样式

解决方案:添加浅色模式样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* 浅色模式 */
.setting-item {
background: #f9fafb;
}

.setting-name {
color: #1f2937;
}

.setting-desc {
color: #6b7280;
}

.setting-input {
border: 1px solid #d1d5db;
background: #fff;
color: #1f2937;
}

/* 深色模式覆盖 */
:global(.dark) .setting-item {
background: rgba(255, 255, 255, 0.05);
}

设计亮点

1. 玻璃拟态(Glassmorphism)风格

1
2
3
4
5
6
7
8
9
10
11
12
.glass-card {
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
}

.glass-card-intense {
background: rgba(255, 255, 255, 0.4);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.5);
}

2. 动态渐变背景

1
2
3
4
5
6
7
8
9
10
11
.animate-gradient-shift {
background: linear-gradient(-45deg, #ffecd2, #fcb69f, #ffecd2, #feada6, #f5efef, #a7bed3);
background-size: 400% 400%;
animation: gradient-shift 15s ease infinite;
}

@keyframes gradient-shift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}

3. 悬浮光晕效果

1
2
3
4
5
6
7
8
.animate-float {
animation: float 8s ease-in-out infinite;
}

@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}

4. 彩色光晕叠加

1
2
3
4
5
6
<div class="absolute inset-0 -z-5 overflow-hidden">
<div class="absolute top-20 left-20 w-72 h-72 bg-orange-300 rounded-full mix-blend-multiply filter blur-3xl opacity-40 animate-float"></div>
<div class="absolute top-40 right-32 w-72 h-72 bg-pink-300 rounded-full mix-blend-multiply filter blur-3xl opacity-40 animate-float-delay"></div>
<div class="absolute -bottom-20 left-1/3 w-96 h-96 bg-purple-300 rounded-full mix-blend-multiply filter blur-3xl opacity-40 animate-float"></div>
<div class="absolute bottom-40 right-20 w-64 h-64 bg-sky-300 rounded-full mix-blend-multiply filter blur-3xl opacity-30 animate-float-delay"></div>
</div>

5. 响应式设计

  • 📱 移动端:底部固定导航栏
  • 🖥️ 桌面端:底部悬浮导航栏
  • 📲 适配各种屏幕尺寸

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
love-study-app/
├── index.html # HTML入口
├── package.json # 项目配置
├── vite.config.js # Vite配置
├── tailwind.config.js # Tailwind配置
└── src/
├── main.js # Vue应用入口
├── router/
│ └── index.js # 路由配置
├── views/ # 页面组件
│ ├── Home.vue # 首页
│ ├── Tasks.vue # 任务管理
│ ├── Focus.vue # 番茄钟
│ ├── Checkin.vue # 习惯打卡
│ ├── Calendar.vue # 日历视图
│ ├── Stats.vue # 数据统计
│ ├── PointsCenter.vue # 积分中心
│ ├── Settings.vue # 设置页面
│ ├── Rewards.vue # 心愿单
│ ├── Journal.vue # 学习心得
│ └── Achievements.vue # 成就徽章
├── components/ # 公共组件
│ ├── Layout.vue # 主布局
│ ├── CalendarView.vue # 日历组件
│ ├── CircularProgress.vue # 环形进度
│ ├── ConfettiEffect.vue # 庆祝动画
│ ├── MoreMenu.vue # 更多菜单
│ └── ...
└── style.css # 全局样式

版本历史

v1.0.0 (2026-02-09)

  • ✨ 初始版本发布
  • 🎨 玻璃拟态UI设计
  • 📱 响应式布局
  • 🔄 深色/浅色模式
  • 💾 LocalStorage持久化

v1.1.0 (2026-02-09)

  • 🎯 通用化倒计时设置
  • 🚀 新增初始化功能
  • 🔧 修复日间模式可见性
  • 🐛 修复硬编码数据问题

部署方式

本地开发

1
2
3
4
5
6
7
# 安装依赖
npm install

# 启动开发服务器
npm run dev

# 访问 http://localhost:3000

生产构建

1
2
3
4
# 构建生产版本
npm run build

# 输出到 dist/ 目录

后续优化方向

  • 添加数据备份到云端
  • 支持多设备同步
  • 添加学习报告导出PDF
  • 支持AI智能生成学习计划
  • 添加社群功能
  • 支持Apple Watch/Android Wear

参考资料


开发感悟:这是一个完全使用纯前端技术栈构建的学习规划应用,通过 LocalStorage 实现了数据的本地持久化。虽然没有后端支持,但通过合理的数据结构设计和本地存储策略,应用能够满足个人学习规划的全部需求。玻璃拟态的UI设计让应用在保持美观的同时,也提供了良好的用户体验。