集合:情绪打卡(checkins)
字数
1426 字
阅读时间
7 分钟
1. 目的与使用场景
- 记录用户每日情绪打卡、任务回执等高敏数据,支撑今天页心情轮、情绪趋势、周报与微建议算法。被今天页、心情随笔清单回执、护心周报云函数使用。
2. Schema 定义
| 字段 | 类型 | 必填 | 默认值 | 约束/校验 | 说明 | 索引 | 权限 |
|---|---|---|---|---|---|---|---|
| _id | string | 是 | - | TCB 自动 | 主键 | PK | P1 |
| _openid | string | 是 | - | TCB 自动 | 创建者 openid | IDX | P2 |
| user_id | string | 是 | - | 指向 users._id | 用户指针 | FK | P2 |
| mood_score | number | 是 | - | 0-100 | 情绪分值 | IDX | P3 |
| mood_tags | array | 否 | [] | 字符串数组 | 场景/人物/地点标签 | - | P3 |
| scene_tags | array | 否 | [] | 字符串数组 | 场景标签 | - | P3 |
| primary_emotion | string | 否 | - | 枚举 | 主情绪类别 | IDX | P3 |
| risk_level | string | 否 | L1 | 枚举 | 风险等级 | IDX | P3 |
| context_note | string | 否 | - | 长度 ≤ 280 | 文本感受摘要 | - | P3 |
| input_type | string | 否 | mood_card | 枚举 | 来源入口 | IDX | P2 |
| related_task_id | string | 否 | - | 指向 tasks._id | 关联任务 | FK | P2 |
| energy_level | number | 否 | - | 0-5 | 能量指数 | IDX | P3 |
| attachments | array | 否 | [] | 附件数组 | 图片/语音引用 | - | P3 |
| mood_wheel_snapshot | object | 否 | - | 心情轮数据 | 心情轮占比 | - | P3 |
| checkin_date | date | 是 | - | ISO 日期 | 打卡日期 | IDX | P2 |
| suggestion_ids | array | 否 | [] | 建议ID数组 | 当次建议列表 | - | P2 |
| checkin_count | number | 否 | 1 | ≥1 | 当日打卡次数 | - | P2 |
| createdAt | date | 是 | - | 服务端时间 | 创建时间 | IDX | P1 |
| updatedAt | date | 是 | - | 服务端时间 | 更新时间 | IDX | P1 |
| createdBy | string | 否 | miniapp | - | 创建渠道 | - | P1 |
| updatedBy | string | 否 | miniapp | - | 最近更新渠道 | - | P1 |
| is_deleted | boolean | 否 | false | - | 软删标记 | IDX | P2 |
枚举值:
- primary_emotion:
joy(喜悦),calm(平静),anxious(焦虑),low(低落),anger(愤怒),other(其他) - risk_level:
L1(一般),L2(关注),L3(需要干预),L4(紧急危机) - input_type:
mood_card(情绪卡片),task_receipt(任务回执),night_mode(晚安模式),manual(手动)
3. 索引与唯一约束
- 单字段索引:
user_id、checkin_date、risk_level - 复合索引:
[user_id, checkin_date desc]、[user_id, risk_level, createdAt desc] - 唯一性约束:支持同日多次打卡,以
[user_id, checkin_date, checkin_count]保证唯一性 - 设计理由与查询覆盖说明:今天页与趋势图需按用户查询最近记录;周报生成依赖日期倒序读取;风险等级用于预警和干预;支持同日多次打卡记录情绪变化。
4. 访问控制(TCB 权限)
json
{
"read": "_openid == auth.openid || auth.role in ['counselor']",
"write": "_openid == auth.openid || auth.role in ['ops','counselor']"
}角色说明:本人可读写;辅导员可在危机干预时补录;运营仅在授权后可代为编辑。
- 关系与级联
引用:
user_id→usersrelated_task_id→taskssuggestion_ids→suggestions
删除策略:
- 用户注销时软删并脱敏
context_note;相关任务回执保留引用但标记related_checkin_id=null。
反范式字段:
mood_wheel_snapshot存储计算结果以减少前端计算;更新时由云函数刷新。
- 数据生命周期与合规
- 留存时长:保留 3 年供纵向分析,超过时段匿名化(仅留 mood_score/mood_tags 聚合)。
- 匿名化:脱敏
context_note、移除附件。 - 用户请求导出时提供加密 CSV;删除时软删并触发清理函数。
- 审计字段:
createdAt、updatedAt、createdBy、updatedBy、input_type。
API/云函数契约映射 | 接口/函数 | 读/写 | 使用字段 | 过滤条件 | 排序/分页 | 备注 | |
/api/moods/today| 读 | mood_score, mood_tags, primary_emotion, checkin_date, mood_wheel_snapshot, risk_level |user_id = auth.uid当日 | - | 今天页展示 | |/api/moods/trend| 读 | mood_score, mood_tags, checkin_date, risk_level |user_id = auth.uid,时间范围 |checkin_date asc| 趋势图 | | 任务回执云函数taskReceipt| 写 | mood_score, context_note, related_task_id, input_type | - | - | 来自任务闭环 | |/api/checkins(草案) | 写 | mood_score, mood_tags, scene_tags, energy_level, risk_level | - | - | 直连情绪打卡 | | 风险监测服务riskMonitor| 读 | mood_score, risk_level, context_note |risk_level in ['L3','L4']|createdAt desc| 风险预警 |示例文档(≥3条)
json
{
"_id": "ck_20240406_a",
"_openid": "oAbcd123",
"user_id": "usr_001",
"mood_score": 72,
"primary_emotion": "calm",
"mood_tags": ["校园", "自习室"],
"context_note": "专注学习但略累",
"input_type": "mood_card",
"checkin_date": "2024-04-06",
"suggestion_ids": ["sg_001","sg_004"],
"createdAt": "2024-04-06T09:00:00Z",
"updatedAt": "2024-04-06T09:00:00Z"
}
{
"_id": "ck_20240406_b",
"_openid": "oAbcd456",
"user_id": "usr_002",
"mood_score": 45,
"primary_emotion": "anxious",
"mood_tags": ["室友", "噪音"],
"context_note": "室友打游戏有点吵",
"input_type": "mood_card",
"energy_level": 2,
"checkin_date": "2024-04-06",
"createdAt": "2024-04-06T13:10:00Z",
"updatedAt": "2024-04-06T13:12:00Z"
}
{
"_id": "ck_20240407_task",
"_openid": "oAbcd123",
"user_id": "usr_001",
"mood_score": 80,
"primary_emotion": "joy",
"context_note": "完成冥想任务感觉放松",
"input_type": "task_receipt",
"related_task_id": "task_305",
"checkin_date": "2024-04-07",
"createdAt": "2024-04-07T20:05:00Z",
"updatedAt": "2024-04-07T20:05:00Z"
}- 常用查询样例(≥3条)
javascript
// 近 7 天情绪趋势
const trend = await db.collection('checkins').where({
user_id: auth.uid,
checkin_date: db.command.gte('2024-03-31')
}).orderBy('checkin_date', 'asc').get();
// 查找任务回执对应的打卡
const receipt = await db.collection('checkins').where({ related_task_id: taskId }).limit(1).get();
// 辅导员查看近 24 小时情绪分值低于 40 的记录
const alerts = await db.collection('checkins').where({
mood_score: db.command.lt(40),
createdAt: db.command.gte(new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString())
}).orderBy('createdAt', 'desc').limit(100).get();- 边界与错误码
- 重复打卡:同日已有记录时返回
E_DUP_CHECKIN,提示改为更新。 - 并发更新:采用事务写入,冲突返回
E_CONFLICT并附带最新版本。 - 越权:非本人修改返回
E_FORBIDDEN并记录审计。
- 变更影响评估
- 调整
mood_score精度需同步埋点事件mood_checkin_submit参数。 - 新增字段需更新周报生成器与数据仓库导出。
- 假设与待确认
- 假设
auth.uid为 users 集合_id,由登录云函数写入;待确认 TCB 环境是否启用自定义登录。 - 待确认情绪附件是否需要单独 COS bucket 分类加密。