Skip to content

集合:心情随笔(journals)

字数
1644 字
阅读时间
8 分钟

1. 目的与使用场景

  • 存储心情随笔与 REBT 结构化记录,支撑心情随笔页、护心周报、微建议生成以及从心情随笔转化任务的流程。由 /api/journals、周报生成云函数、情绪趋势分析使用。

枚举值

  • entry_type: text(文本)、voice(语音)、image(图片)、mixed(混合)、template(模板)
  • share_scope: private(私密)、guardian(守护者)、shared_link(分享链接)
  • risk_level: L1(一般)、L2(关注)、L3(需要干预)、L4(紧急危机)
  • source: journal_page(随笔页)、quick_note(快速记录)、mood_card(情绪卡片)

2. Schema 定义

字段类型必填默认值约束/校验说明隐私分级
_idstring-TCB 自动主键P3
_openidstring-TCB 自动创建人 openidP3
user_id指针id-指向 users._id用户指针P3
entry_typestringtext枚举(text/voice/image/mixed/template)记录类型P2
titlestring-长度 ≤ 40可选标题P1
body_textstring-长度 ≤ 4000文本正文或语音转写P3
mood_scorenumber-0-100情绪分值P3
mood_tagsarray[]元素长度 ≤ 20标签云来源P3
scene_tagsarray[]元素长度 ≤ 20场景标签P3
media_refsarray[]元素为 object {type,url,metadata}附件引用(支持语音/图片/手写OCR)P3
rebt_structobject-A/B/C/D/E 字段REBT 结构化内容P3
ocr_textstring-长度 ≤ 2000OCR识别文本P3
derived_summaryobject-{title, bullet_points[], keywords[]}AI 摘要(包含关键词)P2
generated_task_idsarray[]指向 tasks._id转任务引用P2
share_scopestringprivate枚举(private/guardian/shared_link)分享范围P2
risk_levelstringL1枚举(L1/L2/L3/L4)风险等级P3
allow_suggestion_trainingboolfalse-是否用于建议模型训练P2
sourcestringjournal_page枚举(journal_page,quick_note,mood_card)创建入口P1
is_favoritedboolfalse-收藏标记P1
audio_durationnumber-≥0音频时长(秒)P2
word_countnumber-≥0文本字数统计P1
createdAtdate-服务端时间创建时间P1
updatedAtdate-服务端时间更新时间P1
deletedAtdate--软删时间P2
is_deletedboolfalse-软删标记P2

3. 索引与唯一约束

  • 单字段索引:user_idcreatedAtshare_scoperisk_level
  • 复合索引:[user_id, createdAt desc][user_id, is_deleted, share_scope][user_id, risk_level, createdAt desc]
  • 唯一性约束:无(按 _id)
  • 设计理由:心情随笔列表按时间倒序;分享过滤需按 share_scope;软删过滤避免返回删除记录;风险等级用于连续负向情绪检测。

4. 访问控制(TCB 权限)

json
{
  "read": "_openid == auth.openid || (share_scope == 'guardian' && auth.role == 'guardian') || auth.role in ['counselor']",
  "write": "_openid == auth.openid || auth.role in ['counselor']"
}

角色说明:用户可读写自身;授权守护者可读 share_scope=guardian 的记录;辅导员在紧急情况下可写入备注。

  1. 关系与级联
  • user_idusers
  • generated_task_idstasks
  • checkins 通过日期关联,用于情绪趋势
  • 删除策略:软删保留审计;删除时清空 derived_summary 并解除任务关联。
  • 反范式:derived_summary 缓存周报摘要;更新正文时需刷新。
  1. 数据生命周期与合规
  • 留存:用户主动删除即软删,默认保留 2 年;过期后提供导出备份后删除正文。
  • 匿名化:导出时可生成去标识摘要;模型训练前需脱敏处理。
  • 导出流程:用户在“我的-数据导出”发起 → 云函数压缩 JSON → COS 临时链接。
  • 审计字段:createdAtupdatedAtdeletedAtallow_suggestion_training
  1. API/云函数契约映射 | 接口/函数 | 读/写 | 使用字段 | 过滤条件 | 排序/分页 | 备注 | | /api/journals GET | 读 | title, body_text, mood_score, mood_tags, scene_tags, createdAt, rebt_struct, risk_level | user_id = auth.uid, is_deleted=false | createdAt desc, 分页 | 心情随笔列表 | | /api/journals POST | 写 | entry_type, body_text, mood_score, mood_tags, scene_tags, rebt_struct, share_scope | _openid = auth.openid | - | 创建记录 | | /api/journals PATCH | 写 | title, body_text, mood_tags, share_scope | _id 匹配 | - | 编辑 | | /api/moods/trend | 读 | mood_score, mood_tags, createdAt | user_id = auth.uid | - | 标签云 | | 周报云函数 generateWeeklyReport | 读 | mood_score, mood_tags, derived_summary | 周期内 user_id | - | 护心周报 | | 连续负向检测 consecutiveNegativeCheck | 读 | mood_score, risk_level, createdAt | user_id = auth.uid, 最近2条 | createdAt desc | 负向情绪预警 |

  2. 示例文档(≥3条)

json
{
  "_id": "jr_20240406_01",
  "_openid": "oAbcd123",
  "user_id": "usr_001",
  "entry_type": "text",
  "title": "与室友调解",
  "body_text": "今天和室友聊开了噪音问题,心情平稳不少。",
  "mood_score": 68,
  "mood_tags": ["室友", "沟通"],
  "scene_tags": ["宿舍"],
  "rebt_struct": {"A": "室友打游戏很吵", "B": "他们不尊重我", "C": "焦虑", "D": "尝试约定时间", "E": "得到了理解"},
  "derived_summary": {"title": "成功沟通解决噪音问题", "bullet_points": ["主动沟通", "得到理解"], "keywords": ["沟通", "解决"]},
  "risk_level": "L1",
  "generated_task_ids": ["task_305"],
  "share_scope": "private",
  "word_count": 28,
  "createdAt": "2024-04-06T13:20:00Z",
  "updatedAt": "2024-04-06T13:20:00Z"
}
{
  "_id": "jr_20240405_02",
  "_openid": "oAbcd456",
  "user_id": "usr_002",
  "entry_type": "voice",
  "body_text": "语音转写:今天状态不佳,准备尝试冥想。",
  "mood_score": 42,
  "mood_tags": ["焦虑", "学习"],
  "scene_tags": ["自习室"],
  "share_scope": "guardian",
  "risk_level": "L2",
  "audio_duration": 15,
  "allow_suggestion_training": false,
  "createdAt": "2024-04-05T21:05:00Z",
  "updatedAt": "2024-04-05T21:06:00Z"
}
{
  "_id": "jr_20240404_ocr",
  "_openid": "oAbcd123",
  "user_id": "usr_001",
  "entry_type": "mixed",
  "source": "quick_note",
  "body_text": "今天手写记录了感恩日记,感觉心情变好了。",
  "ocr_text": "感恩日记:1. 好天气 2. 同学帮助 3. 健康身体",
  "media_refs": [{"type": "image", "url": "cos://journal-img-001.jpg", "metadata": {"width": 1080, "height": 1920}}],
  "mood_score": 75,
  "risk_level": "L1",
  "share_scope": "private",
  "word_count": 26,
  "createdAt": "2024-04-04T10:10:00Z",
  "updatedAt": "2024-04-04T10:10:00Z"
}
  1. 常用查询样例(≥3条)
javascript
// 心情随笔列表(分页)
const page = await db.collection('journals')
  .where({ user_id: auth.uid, is_deleted: false })
  .orderBy('createdAt', 'desc')
  .skip(20 * pageIndex)
  .limit(20)
  .get();

// 统计近一月情绪标签
const tags = await db.collection('journals').where({
  user_id: auth.uid,
  createdAt: db.command.gte(new Date(Date.now() - 30 * 86400000).toISOString())
}).field({ mood_tags: true }).get();

// 守护者获取可见心情随笔
const guardianView = await db.collection('journals').where({
  share_scope: 'guardian',
  user_id: targetUserId,
  is_deleted: false
}).orderBy('createdAt', 'desc').get();
  1. 边界与错误码
  • 超长正文:超过 4000 字返回 E_JOURNAL_TOO_LONG
  • 并发编辑:检测 updatedAt,冲突返回 E_VERSION_MISMATCH
  • 越权:未授权守护者访问返回 E_FORBIDDEN 并记录日志。
  1. 变更影响评估
  • 新增字段需同步 /api/journals DTO、护心周报模板、周报推送通知内容。
  • 索引调整影响心情随笔搜索性能及埋点 journal_entry_submit 的查询报表。
  1. 假设与待确认
  • 假设 share_scope='guardian' 通过守护者列表控制,待确认是否存在多守护者差异化权限。
  • 待确认 REBT 结构是否需要单独拆表用于 AI 训练。

贡献者

The avatar of contributor named as Cai Hongyu Cai Hongyu

文件历史

撰写