社区是 HealthLoop 四个 Tab 之一,但它的需求里有一条不太起眼、却决定整轮工作量的规则:
在审核、平台类目和运营能力完成前,社区 Tab 仅展示明确的未开放状态,不提供伪造互动。
这条规则的存在意义,是防止一件很常见的事:为了"看起来在做",先放一个假信息流——几张示例帖、几个点赞数、一句"即将上线"。用户点进去点不到任何东西,产品却已经在暗示社区可用。
这一轮的选择是:页面诚实,契约扎实,云端读写显式延期。
三个前置条件,一个都不满足
| 前置 | 现状 |
|---|---|
| 服务端内容审核通道 | 内容安全校验链路已接,但未在部署环境核验 |
| 平台类目与结论 | 未取得社区形态可上线的确认 |
| 运营处置能力 | 举报如何处置、谁复核、多久响应都没有 |
审核通道不可用的情况下,写路径的价值是负的:
- 用户发了帖,审核结论只能是
pending,对其他人永远不可见——用户看到的是"发了但没人看得到"; - 建了
community_posts集合后,如果类目结论不利,这些数据既不能公开也无法交付; - 举报入口在没有处置端的情况下形同虚设,而举报数据本身是敏感运营信息。
所以在三件事都落地之前不建集合、不建云函数、不开写路径,把延期范围与解锁条件写进 spec。这不是静默裁剪:需求里政策关键的部分全部落地了,只是没有伪装成"已上线"。
后来平台类目结论确认对个人主体不开放,这个决策的代价直接兑现为零:只需切注册、不删实现,重新上线的成本从"重写"降到"注册 + 部署"。
后期很难回改的部分,必须现在做
社区一旦上线,最贵的错误是泄漏和复活:分享训练时把重量、备注、甚至体重饮食带出去;未审核内容被看到;作者删了帖,别人的客户端缓存里还在。
这三类都不是 UI 问题,而是数据契约与判定规则问题——上线后再改等于全量回刷。所以本轮把它们做成纯域函数 + 自检:
resolveCommunityAvailability 开放判定(三项全就绪才 open)
buildTrainingShareDraft 分享草稿:重量与备注默认 null,键集合受白名单约束
isPostVisibleToOthers 仅 approved 且未删除
canUserModifyPost / softDeletePost 仅作者可改删、软删幂等
listVisiblePosts 只取可见内容 + 游标分页
addBlockedAuthor / filterBlockedAuthors 屏蔽
"默认不公开"要做成结构事实
需求说分享时"默认不公开重量、体重、饮食或训练日志"。如果只是"UI 上不勾选就不传",那默认值就是调用方的自觉。改成域层决定:
buildTrainingShareDraft(input, { includeWeights: false, includeNotes: false })
// → { ..., weights: null, notes: null }
草稿的键集合还被常量限制为 8 个字段,结构里根本没有体重/饮食/逐组日志的位置。自检直接断言 Object.keys(draft) 落在白名单内。
可见性与缓存复活
对外可见 = reviewStatus === 'approved' && deletedAtMs === null。列表函数只在这个集合上做分页,因此已删除内容不可能"复活"——不是靠客户端清缓存,而是列表层根本不会返回它。
页面:把"未开放"说清楚
社区
未开放
[内容审核] [平台类目] [运营能力]
- 不写"筹备中"这种模糊词,直接说未开放,并列出具体缺哪几项;
- 不请求任何列表,不显示任何数字——没有点赞、评论数、粉丝、浏览量;
- 开放判定来自一个集中的开关,三项布尔值默认
false并注明依据。
自检用否定断言守两条:页面不得出现"点赞/评论数/粉丝/浏览量/热度",页面 TS 不得出现云函数调用。
两个踩坑
隔离断言把"重量"也禁了——但重量是用户可显式勾选公开项。规则原话是"默认不公开重量",不是"不得公开重量"。断言改为针对真正的私有档案字段(身高/体重/饮食/睡眠/体脂),"默认不公开"交给草稿的 null 语义和键白名单去守。隔离断言的禁止名单要对着规则原文写,不能凭直觉扩大。
注释里的词也会命中静态断言。"域不接触 storage/网络"的断言正则 /wx\.|storage/i,被自己文件头注释里那句"全部不接触 storage / 网络"命中,直接失败。改为匹配真实调用形态(wx.getStorage / wx.cloud / callFunction)。静态断言本质是在源码里做字符串搜索,注释、文档字符串都是噪声源,要锚定到最小可执行形态。
为什么这个"没做什么"值得写下来
延期本身不产生代码,但延期的形状影响很大:
- 契约先行:可见性、软删、分页、白名单在开放前定死,开放时是"接线"不是"设计";
- 页面诚实:列出缺什么,而不是用占位内容暗示能用;
- 零脏数据风险:没建集合就没数据要清理,结论不利时成本归零;
- 解锁条件成文:什么时候能做、做了要验收什么,写进 spec 而不是写在记忆里。
"未开放"是一种交付状态,不是没交付。