# MindScope

一个中文心理量表与自我探索测试项目。项目专注于答题、浏览器本地计分和完整记录导出，不包含 AI 分析、用户账户、数据库、广告、营销页面或 Web3 功能。

> 测评结果仅用于自我了解、教育和研究参考，不构成医学诊断、心理诊断或治疗建议。遇到持续、严重或紧急的身心困扰时，请及时联系医生、心理健康专业人员或当地紧急援助服务。

## 当前版本

**v0.2.0**，发布于 2026-06-23。

本次版本从单次浏览器测评升级为可长期使用的本地测评档案：

- 新增多人档案，可分别保存自己、家人或朋友的测评
- 使用 IndexedDB 保存全部历史，同一量表重复测评不会覆盖旧记录
- 新增 PHQ-9、GAD-7、WHO-5、DASS-21、PSS-10、BDI-II、SDS 和 ISI 趋势追踪
- 新增 Big Five、HEXACO、RIASEC 和 Schwartz 统一画像
- 新增单次 MD、个人完整 MD、全量 JSON 导出与恢复
- 新增基于 PBKDF2 和 AES-GCM 的密码加密备份
- 新增重测周期提示和一键清除本地数据
- 新增 Vitest 自动测试，覆盖计分临界值、反向计分和加密备份
- 结果答案继续保留在浏览器本地，不写入 URL，也不发送给 AI 或第三方分析服务

### 版本记录

| 版本 | 日期 | 主要变化 |
| --- | --- | --- |
| v0.2.0 | 2026-06-23 | 多人档案、完整历史、趋势、统一画像、MD/JSON 导出、加密备份及自动测试 |
| v0.1.0 | 2026-06-22 | 中文量表列表、浏览器答题、本地计分、草稿保存和单次结果导出 |

## 项目特点

- **仅中文内容**：界面、题目、结果说明均为中文
- **32 个测评**：覆盖人格、认知、情绪、睡眠、职业和心理健康
- **本地计算**：答题和计分在浏览器中完成，不依赖外部分析服务
- **无需账户**：没有注册、登录和个人资料系统
- **无需数据库**：默认部署不需要 MySQL、PostgreSQL、Redis 等服务
- **草稿保存**：未完成的答题记录保存在当前浏览器
- **多人档案**：可为自己、家人或朋友分别保存独立记录
- **长期记录**：同一量表每次测评都会新增历史，不覆盖旧结果
- **趋势与画像**：追踪适合重测的量表，并汇总透明的人格维度
- **完整导出**：支持单次或单人全部记录的 Markdown，以及全量 JSON 备份
- **加密备份**：可使用本地密码生成 AES-GCM 加密备份
- **适合轻量部署**：支持 Next.js standalone 构建，可运行在普通 Linux VPS

## 已收录测评

当前共收录 32 个测评。

### 人格

| 测评 | 题数 | 主要内容 |
| --- | ---: | --- |
| IPIP Big Five | 50 | 开放性、尽责性、外向性、宜人性、情绪稳定性 |
| IPIP Big Five 120 | 120 | 五大人格及更细分的人格侧面 |
| IPIP Big Five 300 | 300 | 五大人格完整版及细分侧面 |
| Rosenberg 自尊量表 | 10 | 整体自尊与自我价值感 |
| Grit-S 坚毅量表 | 8 | 兴趣一致性与努力坚持 |
| Brief Self-Control 自控力量表 | 13 | 冲动控制、自律与习惯管理 |
| ECR-RS 亲密关系依恋量表 | 9 | 依恋焦虑与依恋回避 |
| IRI 人际反应指数量表 | 28 | 共情、观点采择与个人忧虑 |
| Short Dark Triad | 27 | 马基雅维利主义、自恋与精神病态倾向 |
| HEXACO | 60 | 诚实谦逊及六因素人格结构 |
| Fisher 气质量表 | 40 | 探索者、建设者、指挥者与协商者倾向 |
| Schwartz 价值观量表 | 30 | 十类基本价值观及高阶价值维度 |
| VIA 性格优势量表 | 48 | 24 项性格优势与六类美德 |
| 开放式九型人格量表（OEPS） | 54 | 九型人格倾向 |
| NPI-16 自恋人格量表 | 16 | 自恋相关人格倾向 |

### 认知

| 测评 | 题数 | 主要内容 |
| --- | ---: | --- |
| CRT 认知反思测试 | 7 | 直觉反应与分析性思考 |
| Need for Cognition | 18 | 主动思考和享受认知活动的倾向 |
| Maximizer | 13 | 决策中的最大化倾向 |
| 成人 ADHD 自评量表（ASRS-v1.1） | 18 | 注意力、冲动和执行功能相关表现 |

### 情绪

| 测评 | 题数 | 主要内容 |
| --- | ---: | --- |
| DASS-21 | 21 | 抑郁、焦虑与压力 |
| GAD-7 | 7 | 广泛性焦虑症状筛查 |
| PHQ-9 | 9 | 抑郁症状筛查 |
| PSS-10 | 10 | 主观感知压力 |
| BDI-II | 21 | 抑郁相关症状自评 |
| SDS | 20 | 抑郁相关症状自评 |

### 心理健康与睡眠

| 测评 | 题数 | 主要内容 |
| --- | ---: | --- |
| WHO-5 幸福感指数 | 5 | 近期主观幸福感 |
| Yale-Brown 强迫症状量表 | 10 | 强迫观念与强迫行为严重程度 |
| SCL-90 | 90 | 多维度心理症状自评 |
| ISI 失眠严重程度指数 | 7 | 失眠程度及日间影响 |
| 性别认知障碍问卷（GDQ） | 27 | 性别相关体验自评 |

### 职业

| 测评 | 题数 | 主要内容 |
| --- | ---: | --- |
| RIASEC 霍兰德职业兴趣量表 | 48 | 现实型、研究型、艺术型、社会型、企业型、常规型 |
| Career Anchors 职业锚 | 40 | 八类职业价值与职业定位 |

## 数据与隐私

项目默认没有服务端数据库，也不会主动把答案发送给第三方分析服务。

| 数据 | 保存位置 | 保存时间 |
| --- | --- | --- |
| 未完成答题草稿 | 浏览器 `localStorage` | 用户清除草稿或浏览器站点数据前 |
| 最近完成的答题答案 | 浏览器 `sessionStorage` | 当前标签页会话结束前 |
| 人物档案与全部测评历史 | 浏览器 `IndexedDB` | 用户删除记录或浏览器站点数据前 |
| 测评结果 Markdown | 用户主动下载的位置 | 由用户自行管理 |
| JSON 或加密 JSON 备份 | 用户主动下载的位置 | 由用户自行管理 |

结果页 URL 不携带答案，因此答案不会因为复制页面链接而进入浏览器历史、代理日志或服务器访问日志。复制结果链接只复制页面地址，不包含测评记录；如需保留或交给其他工具分析，请使用“复制完整记录”或“下载 MD”。

本地保存不等于绝对安全。使用公共电脑时，完成测评后应关闭标签页，并根据需要清除站点数据或已下载文件。

## 技术栈

- Next.js 15（App Router）
- React 19
- TypeScript 5
- Tailwind CSS 4
- next-international
- Radix UI
- Lucide React
- pnpm

## 环境要求

- Node.js 20 或更高版本
- pnpm 9 或更高版本

建议在开发和生产环境使用相同的 Node.js 主版本，避免依赖构建结果不一致。

## 获取与更新项目

推荐使用 SSH 克隆。Gitea 的 SSH 服务使用 `2222` 端口：

```bash
git clone ssh://git@git.polarisx.net:2222/mikemoi/MindScope.git
cd MindScope
```

也可以使用 HTTPS：

```bash
git clone https://git.polarisx.net/mikemoi/MindScope.git
cd MindScope
```

私有仓库通过 HTTPS 克隆时，请使用 Gitea 用户名和访问令牌，不要把账户密码或访问令牌写进命令、脚本或仓库文件。

服务器已经部署过项目时，使用以下命令获取最新版本并重新构建：

```bash
cd /opt/mindscope
git pull --ff-only origin main
pnpm install --frozen-lockfile
pnpm build

mkdir -p .next/standalone/.next
rm -rf .next/standalone/.next/static
cp -r .next/static .next/standalone/.next/static

sudo systemctl restart mindscope
sudo systemctl status mindscope --no-pager
```

如果以后增加了 `public` 目录，构建后还需要同步公开静态文件：

```bash
rm -rf .next/standalone/public
cp -r public .next/standalone/public
```

`.env*`、`.next`、`node_modules`、日志和本地压缩包已被 `.gitignore` 排除，执行 `git pull` 不会提交或下载这些本地运行文件。更新前如有未提交的源码修改，先运行 `git status` 检查；`git pull --ff-only` 会在分支无法安全快进时停止，而不会自动创建合并提交。

## 本地开发

```bash
pnpm install --frozen-lockfile
pnpm dev
```

浏览器打开：<http://localhost:3000>

常用命令：

```bash
# 启动开发服务器
pnpm dev

# 代码检查
pnpm lint

# TypeScript 类型检查
pnpm exec tsc --noEmit

# 自动化计分与加密测试
pnpm test

# 生产构建
pnpm build

# 使用 Next.js 生产服务器启动
pnpm start
```

项目目前不依赖环境变量。`.env*` 文件默认不会进入 Git。

## 生产部署

### 直接运行

适合先验证 VPS 环境：

```bash
pnpm install --frozen-lockfile
pnpm build
NODE_ENV=production PORT=3000 pnpm start
```

生产环境建议只监听本机地址，再由 Nginx 提供公网访问和 HTTPS。

### Standalone 部署

项目在 `next.config.ts` 中启用了 `output: 'standalone'`。构建完成后，可部署更小的运行目录：

```bash
pnpm install --frozen-lockfile
pnpm build

cp -r public .next/standalone/public 2>/dev/null || true
cp -r .next/static .next/standalone/.next/static

cd .next/standalone
HOSTNAME=127.0.0.1 PORT=3000 NODE_ENV=production node server.js
```

当前项目没有 `public` 目录时，第一条复制命令可忽略。`.next/static` 必须复制到 standalone 目录，否则静态资源会缺失。

### systemd 服务示例

假设项目源码部署到 `/opt/mindscope`，Node.js 位于 `/usr/bin/node`：

```ini
[Unit]
Description=MindScope
After=network.target

[Service]
Type=simple
User=mindscope
Group=mindscope
WorkingDirectory=/opt/mindscope/.next/standalone
Environment=NODE_ENV=production
Environment=HOSTNAME=127.0.0.1
Environment=PORT=3000
ExecStart=/usr/bin/node /opt/mindscope/.next/standalone/server.js
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target
```

保存为 `/etc/systemd/system/mindscope.service` 后：

```bash
sudo systemctl daemon-reload
sudo systemctl enable --now mindscope
sudo systemctl status mindscope
```

不要使用 `root` 用户运行应用。部署目录应只允许部署用户写入。

### Nginx 反向代理示例

```nginx
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

配置完成后使用 Certbot 或其他证书工具启用 HTTPS。防火墙通常只需开放 SSH、HTTP 和 HTTPS 端口，应用端口 `3000` 不应直接暴露到公网。

### 推荐 VPS 配置

- 最低：1 核 CPU、1 GB 内存
- 建议：1 核 CPU、2 GB 内存
- 系统：当前受支持的 Debian 或 Ubuntu LTS
- 磁盘：预留至少 2 GB 用于项目、依赖、构建和日志

内存较小的 VPS 可在构建时临时启用 swap，也可以在本地或 CI 构建后只上传 standalone 运行文件。

## 项目结构

```text
MindScope/
├── app/                         # Next.js 页面、布局和全局样式
├── components/
│   ├── questionnaire/
│   │   ├── test/                # 答题流程和各量表计分器
│   │   └── result/              # 结果展示与 Markdown 导出
│   └── ui/                      # 通用界面组件
├── hooks/                       # React Hooks
├── lib/                         # 草稿与结果存储等工具
├── locales/zh/                  # 中文界面文本
├── questionairies/              # 量表题目、说明和元数据
│   └── zh.ts                    # 全部量表注册表
├── types/                       # TypeScript 类型定义
├── middleware.ts                # 中文路由处理
└── next.config.ts               # Next.js 配置
```

目录名 `questionairies` 是项目当前使用的历史命名。新增代码应继续沿用，除非一次性完成全项目重命名，避免导入路径不一致。

## 测评流程

```text
量表列表
  -> 量表详情
  -> 浏览器答题
  -> 本地计分
  -> 结果展示
  -> 复制完整记录或下载 Markdown
```

每个量表主要由三部分组成：

1. `questionairies/<id>/zh.ts`：题目、选项、说明、分类和参考资料
2. `components/questionnaire/test/private/*Calculator.tsx`：答案转换和计分
3. `components/questionnaire/result/analysis/*Result.tsx`：结果解释与展示

`questionairies/zh.ts` 负责把量表注册到列表，`ResultAnalysis.tsx` 负责将量表 ID 分发到对应的结果组件。

## 新增量表

新增量表时建议按以下顺序进行：

1. 在 `questionairies/<id>/zh.ts` 定义量表元数据、题目和选项
2. 在 `questionairies/zh.ts` 导入并注册量表
3. 创建对应的计分组件，处理正向题、反向题和维度得分
4. 创建结果组件，展示总分、维度和必要的边界说明
5. 在 `ResultAnalysis.tsx` 中注册结果组件
6. 运行 `pnpm lint`、`pnpm exec tsc --noEmit` 和 `pnpm build`
7. 手动完成一次答题，检查草稿恢复、结果计算和 MD 导出

量表数据应至少包含：

- 唯一且稳定的 `id`
- 中文标题和简介
- 一级分类与必要标签
- 题数、预计时间和作答说明
- 计分方法和维度说明
- 使用注意事项及参考资料
- 学术认可度、是否适合重测和建议重测周期（适用时）

## 质量检查

提交代码前执行：

```bash
pnpm lint
pnpm exec tsc --noEmit
pnpm test
pnpm build
pnpm audit --audit-level moderate
```

涉及计分逻辑时，还应人工核对：

- 题目编号是否连续且唯一
- 正向题与反向题是否正确
- 选项值是否与计分器一致
- 维度题目数量是否符合预期
- 最低分、最高分和临界值是否可达
- 未答完时能否阻止生成错误结果
- 刷新结果页和关闭标签页后的行为是否符合隐私设计

## 使用边界

- 筛查量表只能提示风险或症状程度，不能单独用于诊断
- 不应根据一次测评结果自行停药、换药或改变治疗方案
- 不同翻译版本、计分版本和适用人群可能存在差异
- 用于正式研究、机构服务或商业场景前，应再次核实量表版本、常模、授权和当地法规
- 项目中的结果解释应保持克制，避免把分数描述为确定的人格或疾病结论

## 授权

本仓库未附带通用开源许可证。项目代码、量表文本及相关材料的复制、修改、再发布和商业使用，应取得仓库权利人的明确许可。第三方量表仍受其各自适用的版权、商标、授权条款和使用规范约束。
