功能(提醒):统一项目提醒中心与桌面通知链路
增加通用提醒状态、数据库迁移和定时同步,覆盖风险时效、文件回执、项目里程碑、访视窗口与协作申请。 新增网页端和桌面端提醒中心、真实投递诊断与固定隐私通知正文,并补齐登录来源聚合、测试和说明文档。
This commit is contained in:
@@ -77,12 +77,12 @@ API:
|
||||
- `POST /api/v1/desktop-notifications/ack`
|
||||
- `POST /api/v1/desktop-notifications/{distribution_id}/read`
|
||||
|
||||
claim 跨有效项目查询匹配当前用户或角色的活动文件分发,使用五分钟租约、唯一约束和事务防重。客户端显示系统通知后 ack;显示失败则等待租约到期后重试。
|
||||
claim 跨有效项目查询当前用户未读且未解决的通用业务提醒,使用五分钟租约、唯一约束和事务防重。客户端显示系统通知后 ack;显示失败则等待租约到期后重试。系统通知只是通用提醒 Feed 的可选投递通道,不单独维护文件分发提醒来源。
|
||||
|
||||
系统通知正文只显示通用内容:
|
||||
|
||||
- 标题:`CTMS 文件更新`
|
||||
- 正文:`有新的文件版本待查看`
|
||||
- 标题:`CTMS 待办提醒`
|
||||
- 正文:`有新的业务提醒待查看`
|
||||
|
||||
项目、文件、版本等详细信息仅在应用内列表显示,避免锁屏泄露。
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
- 文件所有者始终拥有编辑、管理、导出和转让能力;文件管理者始终拥有编辑、管理和导出能力,但不能转让所有权;文件编辑者可以编辑,导出能力由文件“权限设置”开关控制。系统管理员继续保留平台级完整访问能力。
|
||||
- 授予编辑者、管理者或转让所有权时,目标账号必须是当前项目的有效成员,并具备对应项目角色资格;不合格账号在联系人列表中不可选择,后端同时拒绝绕过界面的授权请求。
|
||||
- 文件管理者可开启“允许申请编辑权限”。只读项目成员可从 CTMS 顶栏或 ONLYOFFICE 的“请求编辑”入口提交申请;批准后写入文件级编辑者授权,拒绝或重复处理均有明确状态和审计记录。匿名链接访问者不能申请系统账号权限。
|
||||
- 顶栏铃铛通过通用通知 Feed 展示当前收件人的未关闭通知并记录已读状态;编辑权限申请通知可直接进入对应文件的“权限设置”。原逾期 AE 和逾期监查问题也先同步为通用通知,再由同一 Feed 返回,不再由网页和桌面布局分别临时汇总。
|
||||
- 顶栏铃铛通过通用通知 Feed 展示当前收件人的未关闭通知并记录已读状态;编辑权限申请通知可直接进入对应文件的“权限设置”,审批结果作为一次性信息通知申请人。AE、监查问题、文件回执和里程碑时效提醒也由同一 Feed 返回,具体规则见 `docs/project-notifications.md`。
|
||||
- Excel 文件可通过“允许所有协作者添加、删除工作表”控制工作簿结构。关闭时 CTMS 在新的不可变修订中启用工作簿结构保护并推进文件代次;重新开启时恢复文件原有的工作簿保护状态。该开关作用于所有协作者且不影响单元格内容编辑权限。
|
||||
- 仅文档所有者和系统管理员可转让所有权。目标联系人必须具备文件管理者资格;转让后目标联系人升级为文件管理者,原所有者保留管理者身份,所有权变更写入审计。
|
||||
- 文件编辑器“下载为”由文件导出规则判定:所有者和管理者始终允许,编辑者受文件开关控制,并由 CTMS 网页/桌面文件运行时保存到本机且记录下载审计。“另存为…”还会在项目工作区创建独立协作文件,因此额外要求项目级 `collaboration:create` 权限。
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# 项目提醒中心
|
||||
|
||||
## 产品边界
|
||||
|
||||
项目提醒是既有业务状态面向明确收件人的可操作投影,不是独立任务、日历或聊天系统。源业务记录和业务审计始终是权威数据;提醒的阅读、桌面投递均不能替代 AE 上报、问题关闭、文件回执、审批或其他业务动作。
|
||||
|
||||
当前范围只包括已认证在线客户端:
|
||||
|
||||
- 网页端和桌面端共用当前项目的通用提醒 Feed。
|
||||
- 顶栏铃铛展示摘要,`/project/notifications` 提供当前提醒、未读和待处理筛选。已经解决或因权限变化失效的提醒不再向客户端返回。
|
||||
- 桌面系统通知是用户主动开启的可选投递渠道,只显示不含项目、文件、受试者或风险详情的通用文案。
|
||||
- 不提供离线提醒、本地业务权威数据、个人自由定时任务、短信、即时通讯或浏览器 Push。
|
||||
- 管理员权限监控告警、登录会话提醒和客户端更新“稍后提醒”不进入业务提醒中心。
|
||||
|
||||
## 状态模型
|
||||
|
||||
`notifications` 是收件人级通用提醒表:
|
||||
|
||||
- `read_at`:用户已经看过提醒。
|
||||
- `resolved_at`:源业务已经完成、关闭、失效,或一次性信息通知已经被阅读。
|
||||
- `requires_action`:区分业务待办和一次性信息通知。
|
||||
- `due_at`:用于展示业务截止时间;业务规则仍以源记录为准。
|
||||
- `source_type`、`source_id`、`source_version` 和 `dedupe_key`:用于来源追踪、幂等同步、阶段升级和自动关闭。
|
||||
|
||||
阅读待处理提醒不会写入 `resolved_at`。业务动作完成后由对应服务即时关闭提醒,定时同步还会对遗漏或权限变化进行对账。一次性信息通知在首次阅读时归档。
|
||||
|
||||
桌面投递状态继续保存在 `desktop_notification_deliveries`,但通过 `notification_id` 关联通用提醒。投递成功只记录 `delivered_at`,不自动标记业务提醒已读或已处理;提醒升级或重新打开时可以重新进入桌面投递队列。
|
||||
|
||||
桌面客户端每 60 秒执行一次在线投递检查:先确认本机系统权限,再读取当前账号的服务端订阅,随后领取待投递提醒、调用系统通知并确认实际成功投递的提醒。任一系统通知调用失败时不会确认该条提醒;网络或投递失败采用指数退避,最长 15 分钟。用户可在“设置 → 通知”查看本次客户端运行期间的最近检查、最近投递和当前链路状态,并主动执行一次真实业务提醒检查。
|
||||
|
||||
## 当前规则
|
||||
|
||||
| 来源 | 收件人 | 触发和升级 | 自动关闭 |
|
||||
|---|---|---|---|
|
||||
| 协作编辑申请 | 文件所有者、文件管理者 | 申请创建 | 申请批准或拒绝 |
|
||||
| 协作申请结果 | 申请人 | 申请批准或拒绝 | 申请人阅读后归档 |
|
||||
| 文件分发与回执 | 指定用户、指定角色、中心联系人 | 新分发;3 天内到期;逾期 | 用户完成接收回执、分发关闭或权限失效 |
|
||||
| AE 上报时效 | 具备 AE 读取权限且在中心范围内的项目成员 | 3 天内到期;逾期;按数量增加重新提醒 | 数量归零或权限失效 |
|
||||
| 监查问题整改 | 具备监查问题读取权限且在中心范围内的项目成员 | 3 天内到期;逾期;按数量增加重新提醒 | 数量归零或权限失效 |
|
||||
| 项目里程碑 | 里程碑负责人 | 7 天内到期;逾期;日期或状态变化重新提醒 | 完成、负责人变化或日期移出提醒窗口 |
|
||||
| 受试者访视窗口 | 具备访视更新权限的有效项目成员;CRA 仅限负责中心 | 窗口开始前 3 天、窗口进行中;错过窗口后升级 | 录入实际访视、取消访视、受试者结束、中心停用或权限/中心范围失效 |
|
||||
|
||||
所有规则都要求当前有效项目成员和对应业务权限。系统管理员不会仅因平台权限而批量接收所有项目提醒;需要作为有效项目成员或明确业务收件人进入提醒范围。
|
||||
|
||||
日期型 AE、里程碑和访视窗口规则按 `Asia/Shanghai` 业务日计算,带时区的截止时间统一按 UTC 存储和比较。若未来引入项目级时区,应由项目配置替代固定业务时区,不能使用浏览器本地时区驱动服务端规则。
|
||||
|
||||
访视提醒按访视记录生成并可跳转到对应受试者详情,但提醒标题和正文不包含受试者编号、姓名、中心名称或其他可识别信息。收件人资格以 `visits:update` 及其前置权限为准,避免仅具备只读权限的 PV、QA、CTA 等角色被动接收受试者访视提醒。
|
||||
|
||||
## 同步与诊断
|
||||
|
||||
服务端启动提醒同步任务,默认每 300 秒对所有有效项目成员执行幂等同步;间隔通过 `NOTIFICATION_SYNC_INTERVAL_SECONDS` 配置,允许 60–3600 秒。PostgreSQL advisory lock 防止多个后端进程重复执行全量任务。
|
||||
|
||||
用户读取 Feed 时还会执行一次当前用户轻量对账,用于弥补短时任务失败。单个成员同步失败不会中断其他成员;失败写入 `ctms.notifications` 日志。提醒创建、更新和自动关闭本身不替代源业务审计。
|
||||
|
||||
## 桌面隐私边界
|
||||
|
||||
系统通知固定为:
|
||||
|
||||
- 标题:`CTMS 待办提醒`
|
||||
- 正文:`有新的业务提醒待查看`
|
||||
|
||||
系统通知 API 不接受动态标题或正文。项目名、文件名、版本、受试者、AE、监查问题等详情只允许在完成 token 校验和项目权限确认后的应用内 Feed 中展示;访视提醒即使在应用内 Feed 也不直接显示受试者标识,只通过受控详情路径访问。
|
||||
|
||||
## 系统通知授权边界
|
||||
|
||||
系统权限和服务端订阅是两个独立条件:
|
||||
|
||||
- 首次开启时,客户端先请求操作系统授权;只有操作系统返回已授权,才开启当前账号的服务端订阅。
|
||||
- 用户在操作系统中撤销权限后,服务端订阅可以仍然保持开启,但客户端不会领取提醒,设置页会明确显示“系统权限已拒绝”。
|
||||
- macOS 或 Windows 已拒绝权限时,系统通常不会再次展示授权框。设置页分别引导用户前往“系统设置 → 通知 → CTMS”或“设置 → 系统 → 通知 → CTMS”,返回后通过“重新检测权限”恢复链路。
|
||||
- “发送测试通知”只验证本机通知能力,不访问业务提醒队列;“立即检查业务提醒”会走服务端订阅、领取、系统投递和确认的真实路径。
|
||||
- CTMS 不申请打开任意 URL、执行系统命令或读取操作系统通知内容的额外 Tauri 权限。授权引导仅展示设置路径,避免为便利入口扩大桌面原生能力边界。
|
||||
Reference in New Issue
Block a user