Shabi Type Indicator —— 比 MBTI 更真实的人格测试
一款以幽默戏谑风格设计的 Web 人格测试应用,提供 16 种"整顿社会"人格类型的测试与结果展示。深色霓虹赛博朋克 UI,配合丰富的 Framer Motion 动画体验,仅需 2 分钟即可完成测试。
SBTI 是一个前后端分离的全栈 Web 应用:
- 前端:React 19 + Vite,完整实现人格测试的核心逻辑(题目、计分、结果展示、分享),无需后端即可独立运行
- 后端:Express.js + TypeScript + Prisma,提供可扩展的 REST API 服务框架,对接 PostgreSQL 数据库
- 🎯 12 道情景题,覆盖社交、职场、情绪等真实生活场景
- 🏆 16 种搞笑人格,每种均含详细描述、标签、经典语录、最佳拍档与冤家对头
- 📊 加权计分算法,支持返回上一题重新作答
- 📋 一键复制分享,生成带人格代码与经典语录的分享文案
- 🎨 霓虹赛博朋克 UI,深色主题 +
oklch颜色空间渐变 - ✨ 流畅页面动画,Framer Motion 驱动的浮动 Emoji 背景、题目切换滑动、页面进退场动画
- 📱 响应式设计,移动端与桌面端均可流畅使用
| 类别 | 技术 |
|---|---|
| 框架 | React 19 + TypeScript 5.9 |
| 构建工具 | Vite 7 + @vitejs/plugin-react-swc |
| CSS 框架 | Tailwind CSS v4 + tw-animate-css |
| UI 组件库 | shadcn/ui(New York 风格,基于 Radix UI) |
| 动画 | Framer Motion 12 |
| 路由 | React Router DOM v7 |
| 状态/请求 | TanStack React Query v5 + Axios |
| 表单 | React Hook Form + Zod v4 |
| 图标 | lucide-react |
| 类别 | 技术 |
|---|---|
| 运行环境 | Node.js 18+ |
| Web 框架 | Express.js 4.21+ |
| 开发语言 | TypeScript 5.9+ |
| 数据库 | PostgreSQL 14+(通过 Supabase) |
| ORM | Prisma 6.1+ |
| 参数校验 | Zod 3.24+ |
| 日志 | Pino + pino-http |
| 测试 | Jest 29 + Supertest |
SBTI-test/
├── frontend/ # 前端应用
│ ├── src/
│ │ ├── pages/
│ │ │ ├── Index.tsx # 首页(介绍 + 开始测试)
│ │ │ ├── Test.tsx # 测试页(12 道题答题流程)
│ │ │ ├── Result.tsx # 结果页(人格详情 + 分享)
│ │ │ └── AllTypes.tsx # 全部 16 种人格展览页
│ │ ├── data/
│ │ │ ├── personalities.ts # 16 种人格数据
│ │ │ └── questions.ts # 12 道题目数据
│ │ ├── components/
│ │ │ ├── AnimatedRoutes.tsx
│ │ │ ├── PageTransition.tsx
│ │ │ ├── MotionPrimitives.tsx
│ │ │ └── ui/ # shadcn/ui 组件(40+)
│ │ └── lib/
│ │ └── api-client.ts # Axios 实例
│ ├── vite.config.ts
│ └── package.json
│
└── backend/ # 后端 API 服务
├── src/
│ ├── index.ts # 服务器入口
│ ├── app.ts # Express 应用工厂
│ ├── config/ # 环境变量、数据库、日志
│ ├── middleware/ # 错误处理、日志、校验
│ ├── modules/
│ │ └── system.ts # 健康检查路由
│ └── __tests__/ # 单元测试
├── prisma/
│ └── schema.prisma # 数据库 Schema
├── .env.example
└── package.json
- Node.js 18+
- pnpm(推荐)或 npm
- PostgreSQL 14+(后端可选,前端可独立运行)
# 进入前端目录
cd frontend
# 安装依赖
pnpm install
# 启动开发服务器
pnpm dev浏览器访问 http://localhost:5173
1. 启动后端
cd backend
# 安装依赖
pnpm install
# 复制环境变量配置
cp .env.example .env
# 编辑 .env,填写 DATABASE_URL 等配置
# 生成 Prisma Client
pnpm prisma:generate
# 执行数据库迁移
pnpm prisma:migrate
# 启动开发服务器(含热重载)
pnpm dev后端运行于 http://localhost:3000
2. 启动前端
cd frontend
pnpm install
pnpm dev前端运行于 http://localhost:5173,/api 请求会自动代理至后端 3000 端口。
由于核心测试逻辑完全在前端实现,可以仅部署前端到任意静态托管平台。
构建
cd frontend
pnpm install
pnpm build
# 产物在 frontend/dist/ 目录部署到 Vercel
# 安装 Vercel CLI
npm i -g vercel
cd frontend
vercel --prod部署到 Netlify
# 安装 Netlify CLI
npm i -g netlify-cli
cd frontend
netlify deploy --prod --dir=dist部署到 GitHub Pages / 任意 CDN
将 frontend/dist/ 目录内容上传即可。注意需要配置 SPA 的 404 回退(所有路径回退到 index.html)。
1. 准备生产环境变量
cd backend
cp .env.example .env编辑 .env:
NODE_ENV=production
PORT=3000
API_PREFIX=/api
DATABASE_URL="postgresql://用户名:密码@主机:5432/数据库名?schema=public"
CORS_ORIGIN=https://your-frontend-domain.com
LOG_LEVEL=warn2. 构建 TypeScript
cd backend
pnpm install
pnpm prisma:generate
pnpm prisma:migrate # 或生产环境使用: npx prisma migrate deploy
pnpm build3. 启动生产服务器
pnpm start
# 或使用 PM2 保持进程:
pm2 start dist/index.js --name sbti-backend部署到 Railway
# 在 Railway 控制台新建项目,连接 GitHub 仓库
# 设置 Root Directory 为 backend/
# 添加环境变量后自动构建部署部署到 Render
- 新建 Web Service,连接仓库
- Root Directory:
backend - Build Command:
pnpm install && pnpm prisma:generate && pnpm build - Start Command:
pnpm start - 添加环境变量
修改 frontend/vite.config.ts 中的代理配置,或在生产构建时通过环境变量指定后端 API 地址:
cd frontend
pnpm build然后将 dist/ 部署到 Vercel / Netlify 等平台,并在平台配置:
VITE_API_BASE_URL(如需要)- 重定向规则:所有路径回退到
index.html
后端 Dockerfile(backend/Dockerfile,需自行创建)
FROM node:18-alpine
WORKDIR /app
COPY package*.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm prisma:generate && pnpm build
EXPOSE 3000
CMD ["pnpm", "start"]前端 Dockerfile(frontend/Dockerfile,需自行创建)
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80nginx.conf
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}后端服务统一以 /api 为前缀。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/ |
API 欢迎信息(名称、版本) |
| GET | /api/health |
健康检查(返回 {status: "ok"}) |
| GET | /api/ping |
心跳检测(返回 {message: "pong"}) |
错误响应格式
{
"status": "error",
"message": "错误描述",
"errors": []
}| 变量 | 说明 | 默认值 |
|---|---|---|
NODE_ENV |
运行环境 | development |
PORT |
监听端口 | 3000 |
API_PREFIX |
API 路由前缀 | /api |
DATABASE_URL |
PostgreSQL 连接字符串 | — |
CORS_ORIGIN |
允许的跨域来源(* 或具体 URL) |
* |
LOG_LEVEL |
日志级别(trace/debug/info/warn/error) | info |
⚠️ 生产环境请将CORS_ORIGIN设置为前端的具体域名,避免安全风险。
| 代码 | 名称 | 核心类型 |
|---|---|---|
| 🎭 FAKE | 伪人 | 人格表演型 |
| 💀 DEAD | 死者 | 精神宕机型 |
| 💸 ATM | 送钱者 | 无私兜底付出型 |
| 💩 SHIT | 狗屎人 | 厌世尖锐吐槽型 |
| 🥊 IMSB | 自我攻击者 | 重度内耗自责型 |
| 🐺 SOLO | 精神孤儿 | 灵魂独处孤僻型 |
| 👩👦 MUM | 妈妈型 | 全能操心照料型 |
| 🤡 JOKER | 小丑 | 欢乐面具隐藏型 |
| 🐒 MALO | 吗喽 | 佛系躺平摆烂型 |
| 🤷 OJBK | 无所谓人 | 情绪归零通透型 |
| ✨ SEXY | 风情本体 | 天生松弛魅力型 |
| 😢 CRY | 爱哭包 | 情绪柔软易感型 |
| 🧊 COOL | 高冷人 | 疏离寡淡慢热型 |
| ⚡ ENER | 疯癫乐天派 | 精力旺盛外放型 |
| 🦥 LAZY | 摆烂懒人 | 极致慵懒佛系型 |
| 🍬 SWEET | 甜心体 | 温柔治愈讨好型 |
MIT