# exam-prep **Repository Path**: exam-prep/exam-prep ## Basic Information - **Project Name**: exam-prep - **Description**: 软考考试题库 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-28 - **Last Updated**: 2026-06-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # exam-prep 基于 [Next.js](https://nextjs.org) + [Drizzle ORM](https://orm.drizzle.team) + better-sqlite3 的考试备考练习系统,使用 [`pnpm`](https://pnpm.io) 作为包管理器,常用操作通过根目录的 `Makefile` 统一暴露。 ## 环境要求 - Node.js ≥ 20 - pnpm ≥ 11(推荐通过 Corepack 启用:`corepack enable && corepack prepare pnpm@latest --activate`) - 可正常编译 native 模块的工具链(macOS 上即 Xcode Command Line Tools),因为 `better-sqlite3` 会在安装时执行编译 ## 快速开始 ```bash make install # 安装依赖(首次执行) make db-setup # 初始化 SQLite 数据库 + 写入种子分类 make dev # 启动开发服务器 http://localhost:3000 ``` `.env.local` 中至少需要: ```env AUTH_SECRET=请改成你自己的随机串 NEXTAUTH_URL=http://localhost:3000 ``` ## Makefile 命令 所有日常开发任务都通过 `make` 调用,避免去记忆 pnpm 子命令: | 命令 | 作用 | | --- | --- | | `make help` | 列出所有可用命令 | | `make install` | `pnpm install`,安装/更新依赖 | | `make dev` | 启动 Next.js 开发服务器 | | `make build` | 构建生产版本 | | `make start` | 启动已构建好的生产服务 | | `make lint` | 运行 ESLint | | `make db-setup` | 执行 `src/db/setup.ts`,初始化表结构并写入分类种子数据 | | `make import FILE=…` | 通过 `/api/import` 接口批量导入题库(见下文) | | `make clean` | 删除 `.next` 与 `node_modules` | | `make reinstall` | 清理后重新安装依赖 | > 数据库文件位于 `data/exam.db`(已在 `.gitignore` 中忽略)。删除该文件并重新执行 `make db-setup` 即可重置题库。 ## 导入题库 题库通过管理员账号经 `POST /api/import` 接口写入。系统要求当前登录用户的 `role` 为 `admin`,因此请先通过 `/register` 注册账号、再在数据库中把该账号 `users.role` 改为 `admin`(或通过自带的 seed/迁移脚本预置)。 ### 1. 准备 JSON 文件 文件必须是 `ImportQuestion[]` 数组,每个对象字段如下(与 `src/types/index.ts` 中的 `ImportQuestion` 一致): | 字段 | 类型 | 说明 | | --- | --- | --- | | `subject` | `"comprehensive" \| "case_analysis" \| "essay"` | 所属科目 | | `type` | `"single_choice" \| "multiple_choice" \| "case_analysis" \| "essay"` | 题型 | | `year` | `number` | 真题年份,无则填 `0` | | `categoryName` | `string` | 章节名称,需与数据库中 `categories.name` 完全匹配;找不到时该题的 `categoryId` 将为 `null` | | `difficulty` | `1-5` | 难度等级 | | `content` | `string` | 题干 | | `optionA` ~ `optionD` | `string` | 选项内容,可留空字符串 | | `answer` | `string` | 正确答案,如 `"C"` 或多选 `"AC"` | | `analysis` | `string` | 解析(可空) | | `tags` | `string` | 逗号分隔的标签,例如 `"高频,架构风格"` | `data/questions.sample.json` 示例: ```json [ { "subject": "comprehensive", "type": "single_choice", "year": 2024, "categoryName": "系统架构设计", "difficulty": 3, "content": "以下哪种架构风格最适合需要高可用性的系统?", "optionA": "管道-过滤器风格", "optionB": "事件驱动风格", "optionC": "微服务架构", "optionD": "分层架构风格", "answer": "C", "analysis": "微服务通过服务拆分和独立部署提供更好的高可用性与容错能力。", "tags": "高频,架构风格" } ] ``` ### 2. 执行导入 先确保开发服务器在运行(`make dev`),并已在浏览器登录管理员账号。两种方式任选其一: **方式 A:管理后台** 访问 `/admin/questions`,使用页面上的 "导入" 按钮上传 JSON 文件,导入完成后会弹出 `成功导入 N 道题目`。 **方式 B:Makefile + curl** ```bash # 不带 Cookie(仅在测试环境绕过鉴权时可用) make import FILE=./data/questions.sample.json # 带管理员会话 Cookie(推荐) make import FILE=./data/questions.sample.json \ COOKIE='next-auth.session-token=<从浏览器复制>' ``` 该命令会自动把数组包装为 `{"data": [...]}` 后 POST 到 `http://localhost:3000/api/import`。由于接口要求管理员身份,必须通过 `COOKIE` 参数携带浏览器登录后的会话 Cookie。如果想完全脱离 Makefile,也可以直接: ```bash curl -X POST http://localhost:3000/api/import \ -H "Content-Type: application/json" \ -H "Cookie: next-auth.session-token=<…>" \ -d "{\"data\": $(cat data/questions.sample.json)}" ``` ### 3. 常见问题 - **返回 403 "未授权,需要管理员权限"**:当前登录账号不是 admin,到数据库把 `users.role` 改成 `admin` 后重新登录。 - **题目的 `categoryId` 为空**:JSON 里 `categoryName` 与数据库分类对不上。可以先访问 `/admin/categories` 维护分类,或检查 `make db-setup` 的种子数据。 - **重复导入**:当前导入接口不会去重,会产生重复题目。重复运行前请确保 JSON 内容是新增题目。 ## 项目结构速览 ``` src/ ├── app/ # Next.js App Router 页面与 API │ ├── admin/ # 管理后台(题目、分类) │ ├── api/import/ # 题库导入接口 │ ├── exam/ # 真题模考 │ ├── practice/ # 章节练习 / 随机练习 │ ├── review/ # 复习排程 │ └── ... ├── components/ # UI 组件 ├── db/ # Drizzle schema / 初始化 / 种子 ├── lib/ # 业务工具(含 import-parser) └── types/ # 共享类型(含 ImportQuestion) ``` ## 部署 构建 + 启动: ```bash make build make start ``` 也可参考 [Next.js 部署文档](https://nextjs.org/docs/app/building-your-application/deploying) 部署到 Vercel 等平台。注意生产环境需要: - 持久化 `data/exam.db`(或迁移到其他数据库); - 设置真实的 `AUTH_SECRET` 与 `NEXTAUTH_URL`; - 由于 `better-sqlite3` 需要原生模块,请在与运行环境一致的镜像中执行 `pnpm install`。