集合:用户(users)
1. 目的与使用场景
- 存储微信登录用户的基础资料、账号状态与守护配置。主要由“我的”页、账号与资料管理、隐私授权中心等模块读取;由登录云函数、资料编辑接口写入。
2. Schema 定义
| 字段 | 类型 | 必填 | 默认值 | 约束/校验 | 说明 | 索引 | 权限 |
|---|---|---|---|---|---|---|---|
| _id | string | 是 | - | TCB 自动生成 | 主键 | PK | P1 |
| _openid | string | 是 | - | TCB 自动生成 | 微信 OpenID | UK | P2 |
| nickname | string | 是 | - | 长度 1-32 | 昵称 | IDX | P1 |
| avatar_url | string | 否 | - | URL 校验 | 头像 | - | P1 |
| gender | string | 否 | secret | 枚举值 | 性别 | - | P2 |
| birthday | date | 否 | - | ISO 字符串 | 生日 | - | P2 |
| campus_affiliation | string | 否 | - | 长度 ≤ 64 | 校区/院系标签 | IDX | P1 |
| phone_masked | string | 否 | - | ^\+?\d{3,} 脱敏存储 | 紧急联系掩码 | - | P2 |
| string | 否 | - | Email 格式校验 | 邮箱地址 | - | P2 | |
| status | string | 是 | active | 枚举 | 账号状态 | IDX | P1 |
| role | string | 否 | user | 枚举 | 用户角色 | IDX | P1 |
| onboarding_stage | string | 是 | intro_completed | 枚举 | 引导阶段 | IDX | P1 |
| guardian_ids | array | 否 | [] | 元素为指针id | 绑定守护者 | - | P2 |
| counselor_id | string | 否 | - | 指向 users._id | 绑定辅导员 | FK | P2 |
| emergency_contacts | array | 否 | [] | 对象数组 | 紧急联系人 | - | P3 |
| last_login_at | date | 否 | - | ISO 字符串 | 最近登录时间 | IDX | P1 |
| risk_tier | string | 否 | low | 枚举 | 风险画像等级 | IDX | P3 |
| risk_factors | array | 否 | [] | 字符串数组 | 风险因素 | - | P3 |
| preference_profile | object | 否 | - | 偏好设置对象 | - | P1 | |
| consent_version | string | 否 | - | semver | 隐私协议版本 | IDX | P1 |
| is_deleted | boolean | 否 | false | - | 软删标记 | IDX | P1 |
| deleted_at | date | 否 | - | - | 删除时间 | - | P2 |
| last_activity_at | date | 否 | - | - | 最后活动时间 | IDX | P1 |
| badge_ids | array | 否 | [] | 徽章ID数组 | - | P1 | |
| statistics | object | 否 | - | 统计对象 | - | P2 | |
| createdAt | date | 是 | - | 服务端时间 | 创建时间 | IDX | P1 |
| updatedAt | date | 是 | - | 服务端时间 | 更新时间 | IDX | P1 |
| createdBy | string | 否 | system | - | 创建来源 | - | P1 |
| updatedBy | string | 否 | system | - | 更新来源 | - | P1 |
枚举值:
- status:
active(活跃),inactive(未激活),restricted(受限),suspended(暂停) - role:
user(用户),counselor(辅导员),guardian(守护者),ops(运营) - onboarding_stage:
intro_pending(介绍待完成),intro_completed(介绍已完成),feature_unlocked(功能已解锁) - risk_tier:
low(低),mid(中),high(高),critical(紧急) - gender:
male(男),female(女),secret(隐藏)
3. 索引设计
索引策略:
_openid_1: 唯一索引,支持微信登录和用户识别status_1: 状态索引,支持用户状态筛选role_1_status_1: 复合索引,支持角色权限管理campus_affiliation_1_status_1: 复合索引,支持校区用户管理risk_tier_1_last_activity_at_-1: 复合索引,支持风险用户监控counselor_id_1_status_1: 复合索引,支持辅导员学生管理nickname: 全文索引,支持用户搜索
设计理由:
- 登录鉴权依赖
_openid精准匹配 - 运营筛选校区活跃用户需要校区+状态组合
- 风险画像用于预警看板和及时干预
- 辅导员需要快速查找所负责学生状态
4. 访问控制(TCB 权限)
{
"read": "_openid == auth.openid || auth.role in ['ops','counselor','guardian'] || (auth.role == 'counselor' && counselor_id == auth.uid)",
"write": "_openid == auth.openid || auth.role in ['ops']"
}角色与场景说明:普通用户可访问自身记录;运营(ops)可协助修改资料;心理辅导员(counselor)可查看所负责学生;守护者(guardian)有授权查看权限。
- 关系与级联
引用到的集合与外键字段:
guardian_ids指向同集合_id(守护者)。- 多数集合通过
user_id指针引用用户。
删除策略:
- 用户注销时将
is_deleted=true,保留审计字段;相关集合遵循软删与匿名化策略。
反范式字段:
risk_tier与画像服务同步,变更时需触发任务推荐回调。
- 数据生命周期与合规
- 留存时长:账号注销后 30 天保留备份,其后硬删或脱敏。
- 匿名化策略:清除昵称、头像,保留统计字段。
- 导出/删除流程:用户发起注销 → 工单审核 → 云函数
userCleanup执行软删及相关集合脱敏。 - 审计字段:
createdAt、updatedAt、createdBy、updatedBy、last_login_at。
API/云函数契约映射 | 接口/函数 | 读/写 | 使用字段 | 过滤条件 | 排序/分页 | 备注 | |
/api/user/profile| 读 | nickname, avatar_url, gender, birthday, campus_affiliation, onboarding_stage, risk_tier, role, statistics |_openid = auth.openid| - | 我的页展示 | |/api/user/profile| 写 | nickname, avatar_url, gender, birthday, campus_affiliation, emergency_contacts |_openid = auth.openid| - | 资料编辑 | |/api/privacy/consents| 读/写 | consent_version, guardian_ids, counselor_id |_openid = auth.openid| - | 授权中心 | | 登录云函数authLogin| 读/写 | _openid, status, last_login_at, role |_openid = auth.openid| - | 登录态同步 | | 风险监测服务riskMonitor| 读 | risk_tier, risk_factors, last_activity_at |risk_tier in ['high','critical']| - | 风险预警 | | 徽章服务badgeService| 写 | badge_ids, statistics |user_id匹配 | - | 徽章解锁 |示例文档(≥3条)
{
"_id": "usr_001",
"_openid": "oAbcd123",
"nickname": "星河",
"avatar_url": "https://cdn.example.com/avatar/u1.png",
"gender": "secret",
"birthday": "2000-05-15",
"campus_affiliation": "北苑-心理学",
"email": "student@example.com",
"status": "active",
"role": "user",
"onboarding_stage": "feature_unlocked",
"risk_tier": "low",
"risk_factors": [],
"preference_profile": {"theme": "light", "language": "zh-CN", "notification_settings": {"enabled": true, "quiet_hours": ["22:00", "07:00"]}},
"statistics": {"total_checkins": 15, "completed_tasks": 8, "journal_count": 12, "community_helps": 3},
"badge_ids": ["badge_001", "badge_003"],
"consent_version": "1.2.0",
"last_activity_at": "2024-04-06T09:30:00Z",
"createdAt": "2024-03-01T08:00:00Z",
"updatedAt": "2024-04-06T09:30:00Z"
}
{
"_id": "usr_002",
"_openid": "oAbcd456",
"nickname": "Aria",
"gender": "female",
"birthday": "1999-12-03",
"phone_masked": "+86-138****2233",
"email": "aria@example.com",
"status": "restricted",
"role": "user",
"risk_tier": "mid",
"risk_factors": ["学业压力", "社交焦虑"],
"campus_affiliation": "南苑-计算机",
"counselor_id": "counselor_001",
"guardian_ids": ["usr_guard_01"],
"emergency_contacts": [{"name": "母亲", "relationship": "家人", "masked_phone": "+86-139****8888"}],
"consent_version": "1.2.0",
"last_activity_at": "2024-04-05T07:20:00Z",
"createdAt": "2024-03-05T12:10:00Z",
"updatedAt": "2024-04-05T07:20:00Z"
}
{
"_id": "counselor_001",
"_openid": "oAbcd789",
"nickname": "辅导员赵老师",
"email": "counselor@university.edu.cn",
"status": "active",
"role": "counselor",
"risk_tier": "low",
"campus_affiliation": "南苑-计算机",
"createdBy": "ops",
"last_activity_at": "2024-04-06T10:45:00Z",
"createdAt": "2024-02-20T03:20:00Z",
"updatedAt": "2024-03-18T10:45:00Z"
}- 常用查询样例(≥3条)
// 获取当前用户资料
const me = await db.collection('users').where({ _openid: wxContext.OPENID }).get();
// 查询需要辅导员关注的高风险用户
const highRisk = await db.collection('users').where({ risk_tier: 'high', status: 'active' }).orderBy('updatedAt', 'desc').limit(50).get();
// 运营筛选北苑校区受限账号
const restricted = await db.collection('users').where({ campus_affiliation: '北苑-心理学', status: 'restricted' }).get();- 边界与错误码
- 重复提交:
authLogin若检测_openid已存在则返回E_USER_EXISTS,前端刷新 token。 - 角色权限不足:尝试访问超出角色权限的功能返回
E_ROLE_PERMISSION_DENIED。 - 风险用户限制:restricted 状态用户尝试发帖等受限操作返回
E_USER_RESTRICTED。 - 并发冲突:资料编辑采用
updatedAt乐观锁,不一致时返回E_VERSION_MISMATCH。 - 越权访问:非本人读取被拒绝,返回
E_FORBIDDEN,记录审计日志。
- 变更影响评估
- 新增字段需更新
/api/user/profileDTO 与“我的”页渲染。 - 索引调整影响用户画像批处理与埋点
risk_signal_escalate的用户关联。
- 假设与待确认
- 假设守护者也是用户集合中的账号,通过
guardian_ids互联;待确认是否需要独立集合存储外部联系人。 - 待确认
risk_tier更新由谁负责(AI 服务或人工审核)。