我的项目

全部
项目加载中...

我的知识库

企业数字资产
Z

张默寒 · 开发者视图

单词打卡小程序 · 代码开发 · 进行中

main · 12 commits
💻 张默寒(全栈开发)已开始代码开发
张默寒AI14:00
PRD评审通过了!我这就开始搭建项目。 🛠️ 今天的开发计划: 1. 初始化微信小程序项目 2. 搭建Node.js后端服务 3. 连接MongoDB数据库 4. 实现微信登录接口 开干!💪
张默寒AI14:30

📦 项目初始化完成

# 小程序项目结构已创建
word-checkin/
├── pages/
│   ├── index/          # 首页(今日任务)
│   ├── learn/           # 学习页面
│   ├── checkin/         # 打卡页面
│   ├── profile/         # 个人中心
│   └── wordbook/        # 词库选择
├── components/
│   ├── word-card/       # 单词卡片组件
│   ├── calendar/        # 打卡日历组件
│   └── share-poster/    # 分享海报组件
├── utils/
│   ├── api.js           # API请求封装
│   ├── auth.js          # 登录授权
│   └── sm2.js           # SM-2复习算法
├── server/
│   ├── app.js           # Express入口
│   ├── routes/          # API路由
│   ├── models/          # 数据模型
│   ├── middleware/       # 中间件
│   └── config/          # 配置文件
├── app.json
└── package.json
王子轩AI14:35
云环境已就绪! ✅ 腾讯云MongoDB实例已创建 ✅ 连接串已通过密钥管理工具发送 ✅ SCF云函数环境已开通 ✅ GitHub Actions CI/CD流水线已配置 @张默寒 数据库连接信息已发到你的内部邮箱,记得检查。
张默寒AI14:40
收到!数据库连接成功 ✅ 正在编写数据模型...
张默寒AI15:00

📝 用户模型 - models/User.js

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  openId: { type: String, required: true, unique: true },
  nickname: { type: String, default: '微信用户' },
  avatar: String,
  level: {
    type: String,
    enum: ['beginner', 'intermediate', 'advanced'],
    default: 'beginner'
  },
  dailyGoal: { type: Number, default: 20 },
  currentBook: { type: mongoose.Schema.Types.ObjectId, ref: 'WordBook' },
  streak: { type: Number, default: 0 },          // 连续打卡天数
  totalDays: { type: Number, default: 0 },        // 总打卡天数
  totalWords: { type: Number, default: 0 },       // 累计学习单词
  achievements: [{ type: String }],               // 成就勋章
  createdAt: { type: Date, default: Date.now },
});

module.exports = mongoose.model('User', userSchema);
15:05
代码看起来很干净!有个问题:如果用户一天没打卡,streak中断后还能恢复吗?比如有些App可以用金币"补签"。
张默寒AI15:06
好问题!我可以加一个`补签`功能。设计上: • 每个用户每月有 **2次免费补签** 机会 • 补签仅限前一天 • 补签后streak恢复连续状态 在User模型加个字段: ``` makeupChances: { type: Number, default: 2 } lastMakeupReset: { type: Date } // 每月1号重置 ``` @李思远 这个需求要更新到PRD里吗?
李思远AI15:07
应该加上!补签功能可以降低用户因断签而流失的风险。我把它放到P1功能里,MVP先实现基础打卡,V1.1版本加补签。 ✏️ PRD已更新。
张默寒AI15:30

🔐 微信登录接口 - routes/auth.js

const express = require('express');
const router = express.Router();
const axios = require('axios');
const jwt = require('jsonwebtoken');
const User = require('../models/User');

// 微信小程序登录
router.post('/wx-login', async (req, res) => {
  try {
    const { code } = req.body;
    
    // 用code换取openId和session_key
    const wxRes = await axios.get(
      'https://api.weixin.qq.com/sns/jscode2session',
      {
        params: {
          appid: process.env.WX_APPID,
          secret: process.env.WX_SECRET,
          js_code: code,
          grant_type: 'authorization_code',
        },
      }
    );
    
    const { openid, session_key } = wxRes.data;
    
    // 查找或创建用户
    let user = await User.findOne({ openId: openid });
    if (!user) {
      user = await User.create({ openId: openid });
    }
    
    // 生成JWT token
    const token = jwt.sign(
      { userId: user._id, openId: openid },
      process.env.JWT_SECRET,
      { expiresIn: '7d' }
    );
    
    res.json({ success: true, token, user });
  } catch (error) {
    res.status(500).json({
      success: false,
      message: '登录失败',
      error: error.message
    });
  }
});

module.exports = router;
张默寒AI15:35
微信登录接口完成!✅ 已同步在小程序前端实现了对应的登录逻辑。接下来写打卡核心功能...
陈雨桐AI15:40
设计稿第一版出炉啦!🎨 完成了以下页面设计: 📱 首页(今日任务卡片 + 打卡进度环) 📱 学习页(单词卡片翻转动画) 📱 打卡成功页(confetti动画 + 分享按钮) 📱 个人中心(打卡日历 + 数据统计) 整体采用清新活力风格,主色调活力绿+暖橙色。 @张默寒 我标注好了设计稿里的尺寸和间距,你可以开始切页面了。各位要是对设计有修改意见就提出来!
15:45
设计风格很棒!很年轻有活力。有一个小建议:打卡成功页能不能加一句随机的励志名言?类似"坚持就是胜利"这种,给用户一些正向反馈。
陈雨桐AI15:46
好主意!打卡成功时显示一句励志名言,既有仪式感又有温度 ❤️ 我在设计稿里加一个文案卡片区域,让文字有呼吸感。 @张默寒 前端可以准备一组励志名言的JSON数据,每次打卡随机显示一条。
张默寒AI16:00

✅ 打卡接口 - routes/checkin.js

const express = require('express');
const router = express.Router();
const auth = require('../middleware/auth');
const User = require('../models/User');
const CheckIn = require('../models/CheckIn');

// 每日打卡
router.post('/', auth, async (req, res) => {
  try {
    const { wordsLearned, duration, newWords, reviewWords } = req.body;
    const userId = req.user.userId;
    const today = new Date().toISOString().split('T')[0];
    
    // 检查今天是否已打卡
    const existing = await CheckIn.findOne({ userId, date: today });
    if (existing) {
      return res.status(400).json({ message: '今天已经打过卡了!' });
    }
    
    // 创建打卡记录
    const checkIn = await CheckIn.create({
      userId, date: today, wordsLearned, duration, newWords, reviewWords,
    });
    
    // 更新用户统计
    const user = await User.findById(userId);
    const yesterday = new Date(Date.now() - 86400000).toISOString().split('T')[0];
    const yesterdayCheckIn = await CheckIn.findOne({ userId, date: yesterday });
    
    user.streak = yesterdayCheckIn ? user.streak + 1 : 1;
    user.totalDays += 1;
    user.totalWords += wordsLearned;
    
    // 检查成就
    if (user.streak === 7) user.achievements.push('week_warrior');
    if (user.streak === 30) user.achievements.push('monthly_master');
    if (user.totalWords >= 1000) user.achievements.push('word_collector');
    
    await user.save();
    
    res.json({
      success: true,
      checkIn,
      streak: user.streak,
      newAchievements: user.achievements.slice(-1),
      motivationalQuote: getRandomQuote()
    });
  } catch (error) {
    res.status(500).json({ success: false, error: error.message });
  }
});

function getRandomQuote() {
  const quotes = [
    '每一个单词都是通往新世界的钥匙 🔑',
    '坚持就是胜利,你已经比昨天更强了!💪',
    '学习是最好的投资,今天的你很棒!🌟',
    'Rome was not built in a day. 加油!🚀',
    '词汇量+1,离梦想又近了一步 ✨',
  ];
  return quotes[Math.floor(Math.random() * quotes.length)];
}

module.exports = router;
张默寒AI16:05
打卡接口完成!✅ 包含了: • 防重复打卡 • 连续打卡天数计算 • 成就勋章自动解锁(7天/30天/1000词) • 随机励志名言返回 📊 **今日开发进度**: ✅ 项目结构搭建 100% ✅ 微信登录接口 100% ✅ 打卡核心接口 100% 🔨 词库管理接口 进行中... ⏳ 前端页面开发 待开始 整体进度: ████████░░░░ 40%
CEOAI16:10
第一天的开发进度非常棒!🎉 📋 **今日总结**: • 后端核心API已完成3个 • 前端项目骨架已搭建 • UI设计第一版已完成 • 云基础设施全部就绪 按这个速度,第二周可以提前进入联调阶段。 ⏰ 明天继续加油,目标是完成词库模块和前端首页。各位辛苦了!🙏