我用 React 19 + TypeScript 搭了个 AI 智能题库平台,还把它托管上线了(附在线 Demo)

前言

大二下学期,有一门课要求做一个"完整的 Web 应用"作为期末项目。选题的时候我想了很久------做一个普通的 CRUD 管理系统太无聊,做一个电商又太常见。后来看到身边同学都在用各种刷题 App 备考,但要么题型单一、要么手动录入题目累死人、要么没有学习数据分析......

于是我做了一个叫 Cognix​ 的东西:一个支持多用户的智能题库练习平台,可以用 AI 自动从图片、PDF、文本里提取题目,支持选择题、判断题、填空题、简答题等多种题型,还有错题本和学习数据仪表盘。

这篇文章会从技术选型、核心功能实现、部署上线到踩坑经验,完整复盘整个项目的诞生过程。希望能给正在做类似项目的朋友一些参考。


为什么选这套技术栈?

技术 选择理由
React 19 当时刚发布不久,想尝鲜新特性(比如 use() Hook、Server Components 虽然我没用到),而且生态成熟
TypeScript 期末项目也要认真写类型,后期维护和重构时真香
Vite 开发体验极佳,热更新快得像本地文件
Zustand 比 Redux 轻量太多,API 简洁,配合 TypeScript 类型推导完美
React Router v6 嵌套路由 + loader 很适合这种多页面应用
Tailwind CSS 写样式最快的方式,不用切文件,原子化类名
Supabase 后端即服务(BaaS),提供 PostgreSQL 数据库 + 认证 + 存储 + Row Level Security,省去自己写后端 API 的精力
Recharts 轻量图表库,用来画学习趋势折线图和题型分布饼图

说实话,选 Supabase 是我做过最正确的决定之一。作为一个前端为主的学生,我不需要再单独写一个 Node.js 后端,只需要定义好表结构和 RLS 策略,前端直接调用 Supabase SDK 就能完成所有数据操作。


核心功能实现

1. 多题型支持与答题引擎

题库系统最基础的就是题型支持。我设计了统一的 questions表结构:

go 复制代码
interface Question {
  id: string;
  type: 'single_choice' | 'multiple_choice' | 'true_false' | 'fill_blank' | 'short_answer';
  content: string;          // 题干(支持 Markdown)
  options?: string[];       // 选项(选择题用)
  answer: string | string[]; // 正确答案
  explanation?: string;     // 解析
  difficulty: 1 | 2 | 3;    // 难度等级
  tags: string[];           // 知识点标签
}

答题时,每种题型对应不同的渲染组件和判题逻辑。例如多选题允许多选,判题时需要比较数组是否完全一致;填空题则用正则忽略大小写和空格。

小技巧:判题函数全部写成纯函数,方便单元测试。我用 Vitest 写了 50+ 个测试用例覆盖所有题型边界情况。

2. AI 智能导入(这个最值得聊)

传统的题库录入方式是手工一条条打字,效率极低。我的目标是:用户上传一张试卷照片或一段文本,AI 自动解析出结构化题目

实现思路很简单:

  1. 用户上传图片 / PDF / 输入文本 → 前端预览
  2. 调用 OCR(Tesseract.js 或第三方 API)提取文字(如果是图片)
  3. 将提取的文本发送到大模型 API(这里我接入了 OpenAI-compatible 的接口,也可以用国内模型)
  4. Prompt 设计是关键:
javascript 复制代码
你是一个题目解析助手。请从以下文本中提取所有题目,按照 JSON 格式返回:
[
  {
    "type": "single_choice",
    "content": "...",
    "options": ["A. ...", "B. ...", "C. ...", "D. ..."],
    "answer": "A",
    "explanation": "..."
  }
]
注意:判断题答案用 true/false,填空题答案用字符串数组。
  1. 收到返回的 JSON 后,前端进行校验和格式化,然后批量插入数据库

踩坑:大模型有时会返回格式错误的 JSON,或者漏掉题目。我加了两次校验:一次是 JSON.parse 前的正则修复,一次是字段完整性检查,不通过的题目进入"待人工修正"列表,用户可以手动编辑后再导入。

最终效果:导入一份 20 道题的试卷,从上传到入库不到 30 秒,准确率大概 85%------剩下的手动改一下就行,比起逐条输入快了 10 倍不止。

3. 错题分析与学习追踪

每次用户提交答案,系统都会记录一条 attempts记录:

ini 复制代码
interface Attempt {
  id: string;
  user_id: string;
  question_id: string;
  answer_given: string | string[];
  is_correct: boolean;
  created_at: timestamp;
}

基于这些数据,我实现了:

  • 错题本:自动收集所有答错的题目,按知识点分组,支持重新练习
  • 学习仪表盘:用 Recharts 绘制近 7 天正确率趋势、各题型正确率对比、薄弱知识点雷达图
  • 间隔重复提示:根据遗忘曲线,在合适的时间提醒用户复习旧错题

4. 多用户与权限管理

利用 Supabase Auth 实现邮箱注册/登录。每个用户只能看到自己的数据(通过 RLS 策略保证):

sql 复制代码
-- 只允许查看自己的答题记录
CREATE POLICY "Users can view their own attempts"
ON attempts FOR SELECT
USING (auth.uid() = user_id);

部署上线:零成本搞定

前端部署在 EdgeOne (免费,绑定 Gitee/GitHub 仓库自动 CI/CD)。Supabase 本身是 SaaS,不需要额外部署。域名我用的是 cognix.liveling.top

注意事项

  • EdgeOne 环境变量里配置 Supabase URL 和 anon key
  • EdgeOne会自动里配置 rewrites规则,确保所有路由都指向 index.html
  • Supabase 的免费套餐足够个人和小团队使用(500MB 数据库、5GB 带宽)

踩坑总结

  1. RLS 策略调试 :Supabase 的 RLS 一开始总是不生效,后来发现需要在 SQL Editor 里手动启用 FORCE ROW LEVEL SECURITY,并且在客户端使用 select('*')时要确保用户已认证。
  2. AI 导入的稳定性:大模型偶尔会"幻觉"出题目,或者把题干和选项混淆。我在前端加了人工审核弹窗,让用户确认后再入库。
  3. 状态管理:Zustand 虽然好用,但当多个页面共享同一份题库数据时,缓存失效是个坑。最后我用 React Query(TanStack Query)替代了部分 Zustand store,利用它的 cache invalidation 自动刷新。
  4. 移动端适配:Tailwind 的响应式类很方便,但答题时的交互(尤其是多选题拖拽排序)在手机上体验不好,后面改用简单的勾选框。

项目地址与在线体验

如果你也在做类似的项目,或者想找个现成的题库系统来用,欢迎 Star、Fork、提 Issue。也欢迎在评论区交流技术细节!


最后

做这个项目最大的收获不是学会了某个框架,而是如何把一个想法变成可用的产品。从需求分析、技术选型、编码实现到部署上线,每一步都踩了不少坑,但也真正理解了"全栈"的含义。

如果你是相关专业的学生,正在纠结期末项目做什么,我的建议是:找一个真实的需求,哪怕很小,把它做到能用的程度。比起做一个完美的 demo,一个能跑起来、有人愿意用的项目,对你的成长帮助更大。

感谢阅读,希望对你有帮助


写在后面:跪求gitee star 这对我的期末成绩很重要,求求你了orz

相关推荐
大家的林语冰2 小时前
React 生态大迁徙,脸书源码仓库跑路,核心技术栈全员加盟 React 基金会!
前端·javascript·react.js
vim怎么退出4 小时前
Dive into React——高级特性
前端·react.js·源码阅读
Csvn5 小时前
React useEffect 异步竞态:90% 的人都踩过的坑
前端·react.js
qq_363066936 小时前
react 使用web component导出静态html报告
前端·react.js·html·页面导出
放下华子我只抽RuiKe56 小时前
FastAPI 全栈后端(五):后台任务与消息队列
前端·javascript·react.js·ai·前端框架·fastapi·ai编程
小二·7 小时前
React 18 新特性与 Hooks 进阶实战
前端·react.js·前端框架
六月的可乐7 小时前
【干货】小程序虚拟瀑布流探索小结
前端·react.js·小程序
鹤鸣的日常20 小时前
前端运行时动态环境变量方案
前端·react.js·docker·前端框架·vue·gitlab
vim怎么退出1 天前
Dive into React——事件系统
前端·react.js·源码阅读